[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / lib / AST / PrintfFormatString.cpp
blob96079c235c5eb685229a2256789a4b12488f9cd1
1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Handling of format string in printf and friends. The structure of format
10 // strings for fprintf() are described in C99 7.19.6.1.
12 //===----------------------------------------------------------------------===//
14 #include "FormatStringParsing.h"
15 #include "clang/AST/FormatString.h"
16 #include "clang/AST/OSLog.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "llvm/Support/Regex.h"
20 using clang::analyze_format_string::ArgType;
21 using clang::analyze_format_string::FormatStringHandler;
22 using clang::analyze_format_string::LengthModifier;
23 using clang::analyze_format_string::OptionalAmount;
24 using clang::analyze_format_string::ConversionSpecifier;
25 using clang::analyze_printf::PrintfSpecifier;
27 using namespace clang;
29 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
30 PrintfSpecifierResult;
32 //===----------------------------------------------------------------------===//
33 // Methods for parsing format strings.
34 //===----------------------------------------------------------------------===//
36 using analyze_format_string::ParseNonPositionAmount;
38 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
39 const char *Start, const char *&Beg, const char *E,
40 unsigned *argIndex) {
41 if (argIndex) {
42 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
43 } else {
44 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
45 analyze_format_string::PrecisionPos);
46 if (Amt.isInvalid())
47 return true;
48 FS.setPrecision(Amt);
50 return false;
53 static 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;
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);
68 return true;
71 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
72 const char *&Beg,
73 const char *E,
74 unsigned &argIndex,
75 const LangOptions &LO,
76 const TargetInfo &Target,
77 bool Warn,
78 bool isFreeBSDKPrintf) {
80 using namespace clang::analyze_format_string;
81 using namespace clang::analyze_printf;
83 const char *I = Beg;
84 const char *Start = nullptr;
85 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
87 // Look for a '%' character that indicates the start of a format specifier.
88 for ( ; I != E ; ++I) {
89 char c = *I;
90 if (c == '\0') {
91 // Detect spurious null characters, which are likely errors.
92 H.HandleNullChar(I);
93 return true;
95 if (c == '%') {
96 Start = I++; // Record the start of the format specifier.
97 break;
101 // No format specifier found?
102 if (!Start)
103 return false;
105 if (I == E) {
106 // No more characters left?
107 if (Warn)
108 H.HandleIncompleteSpecifier(Start, E - Start);
109 return true;
112 PrintfSpecifier FS;
113 if (ParseArgPosition(H, FS, Start, I, E))
114 return true;
116 if (I == E) {
117 // No more characters left?
118 if (Warn)
119 H.HandleIncompleteSpecifier(Start, E - Start);
120 return true;
123 if (*I == '{') {
124 ++I;
125 unsigned char PrivacyFlags = 0;
126 StringRef MatchedStr;
128 do {
129 StringRef Str(I, E - I);
130 std::string Match = "^[[:space:]]*"
131 "(private|public|sensitive|mask\\.[^[:space:],}]*)"
132 "[[:space:]]*(,|})";
133 llvm::Regex R(Match);
134 SmallVector<StringRef, 2> Matches;
136 if (R.match(Str, &Matches)) {
137 MatchedStr = Matches[1];
138 I += Matches[0].size();
140 // 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.
143 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"))
150 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
151 else if (PrivacyFlags !=
152 clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
153 MatchedStr.equals("private"))
154 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
155 else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
156 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
157 } else {
158 size_t CommaOrBracePos =
159 Str.find_if([](char c) { return c == ',' || c == '}'; });
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;
168 I += CommaOrBracePos + 1;
170 // Continue until the closing brace is found.
171 } while (*(I - 1) == ',');
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;
183 case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
184 FS.setIsSensitive(MatchedStr.data());
185 break;
186 default:
187 llvm_unreachable("Unexpected privacy flag value");
191 // Look for flags (if any).
192 bool hasMore = true;
193 for ( ; I != E; ++I) {
194 switch (*I) {
195 default: hasMore = false; break;
196 case '\'':
197 // FIXME: POSIX specific. Always accept?
198 FS.setHasThousandsGrouping(I);
199 break;
200 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;
206 if (!hasMore)
207 break;
210 if (I == E) {
211 // No more characters left?
212 if (Warn)
213 H.HandleIncompleteSpecifier(Start, E - Start);
214 return true;
217 // Look for the field width (if any).
218 if (ParseFieldWidth(H, FS, Start, I, E,
219 FS.usesPositionalArg() ? nullptr : &argIndex))
220 return true;
222 if (I == E) {
223 // No more characters left?
224 if (Warn)
225 H.HandleIncompleteSpecifier(Start, E - Start);
226 return true;
229 // Look for the precision (if any).
230 if (*I == '.') {
231 ++I;
232 if (I == E) {
233 if (Warn)
234 H.HandleIncompleteSpecifier(Start, E - Start);
235 return true;
238 if (ParsePrecision(H, FS, Start, I, E,
239 FS.usesPositionalArg() ? nullptr : &argIndex))
240 return true;
242 if (I == E) {
243 // No more characters left?
244 if (Warn)
245 H.HandleIncompleteSpecifier(Start, E - Start);
246 return true;
250 if (ParseVectorModifier(H, FS, I, E, LO))
251 return true;
253 // Look for the length modifier.
254 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
255 // No more characters left?
256 if (Warn)
257 H.HandleIncompleteSpecifier(Start, E - Start);
258 return true;
261 // Look for the Objective-C modifier flags, if any.
262 // We parse these here, even if they don't apply to
263 // the conversion specifier, and then emit an error
264 // later if the conversion specifier isn't '@'. This
265 // enables better recovery, and we don't know if
266 // these flags are applicable until later.
267 const char *ObjCModifierFlagsStart = nullptr,
268 *ObjCModifierFlagsEnd = nullptr;
269 if (*I == '[') {
270 ObjCModifierFlagsStart = I;
271 ++I;
272 auto flagStart = I;
273 for (;; ++I) {
274 ObjCModifierFlagsEnd = I;
275 if (I == E) {
276 if (Warn)
277 H.HandleIncompleteSpecifier(Start, E - Start);
278 return true;
280 // Did we find the closing ']'?
281 if (*I == ']') {
282 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
283 return true;
284 ++I;
285 break;
287 // There are no separators defined yet for multiple
288 // Objective-C modifier flags. When those are
289 // defined, this is the place to check.
293 if (*I == '\0') {
294 // Detect spurious null characters, which are likely errors.
295 H.HandleNullChar(I);
296 return true;
299 // Finally, look for the conversion specifier.
300 const char *conversionPosition = I++;
301 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
302 switch (*conversionPosition) {
303 default:
304 break;
305 // C99: 7.19.6.1 (section 8).
306 case '%': k = ConversionSpecifier::PercentArg; break;
307 case 'A': k = ConversionSpecifier::AArg; break;
308 case 'E': k = ConversionSpecifier::EArg; break;
309 case 'F': k = ConversionSpecifier::FArg; break;
310 case 'G': k = ConversionSpecifier::GArg; break;
311 case 'X': k = ConversionSpecifier::XArg; break;
312 case 'a': k = ConversionSpecifier::aArg; break;
313 case 'c': k = ConversionSpecifier::cArg; break;
314 case 'd': k = ConversionSpecifier::dArg; break;
315 case 'e': k = ConversionSpecifier::eArg; break;
316 case 'f': k = ConversionSpecifier::fArg; break;
317 case 'g': k = ConversionSpecifier::gArg; break;
318 case 'i': k = ConversionSpecifier::iArg; break;
319 case 'n':
320 // Not handled, but reserved in OpenCL.
321 if (!LO.OpenCL)
322 k = ConversionSpecifier::nArg;
323 break;
324 case 'o': k = ConversionSpecifier::oArg; break;
325 case 'p': k = ConversionSpecifier::pArg; break;
326 case 's': k = ConversionSpecifier::sArg; break;
327 case 'u': k = ConversionSpecifier::uArg; break;
328 case 'x': k = ConversionSpecifier::xArg; break;
329 // C23.
330 case 'b':
331 if (isFreeBSDKPrintf)
332 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
333 else
334 k = ConversionSpecifier::bArg;
335 break;
336 case 'B': k = ConversionSpecifier::BArg; break;
337 // POSIX specific.
338 case 'C': k = ConversionSpecifier::CArg; break;
339 case 'S': k = ConversionSpecifier::SArg; break;
340 // Apple extension for os_log
341 case 'P':
342 k = ConversionSpecifier::PArg;
343 break;
344 // Objective-C.
345 case '@': k = ConversionSpecifier::ObjCObjArg; break;
346 // Glibc specific.
347 case 'm': k = ConversionSpecifier::PrintErrno; break;
348 case 'r':
349 if (isFreeBSDKPrintf)
350 k = ConversionSpecifier::FreeBSDrArg; // int
351 break;
352 case 'y':
353 if (isFreeBSDKPrintf)
354 k = ConversionSpecifier::FreeBSDyArg; // int
355 break;
356 // Apple-specific.
357 case 'D':
358 if (isFreeBSDKPrintf)
359 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
360 else if (Target.getTriple().isOSDarwin())
361 k = ConversionSpecifier::DArg;
362 break;
363 case 'O':
364 if (Target.getTriple().isOSDarwin())
365 k = ConversionSpecifier::OArg;
366 break;
367 case 'U':
368 if (Target.getTriple().isOSDarwin())
369 k = ConversionSpecifier::UArg;
370 break;
371 // MS specific.
372 case 'Z':
373 if (Target.getTriple().isOSMSVCRT())
374 k = ConversionSpecifier::ZArg;
375 break;
378 // Check to see if we used the Objective-C modifier flags with
379 // a conversion specifier other than '@'.
380 if (k != ConversionSpecifier::ObjCObjArg &&
381 k != ConversionSpecifier::InvalidSpecifier &&
382 ObjCModifierFlagsStart) {
383 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
384 ObjCModifierFlagsEnd + 1,
385 conversionPosition);
386 return true;
389 PrintfConversionSpecifier CS(conversionPosition, k);
390 FS.setConversionSpecifier(CS);
391 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
392 FS.setArgIndex(argIndex++);
393 // FreeBSD kernel specific.
394 if (k == ConversionSpecifier::FreeBSDbArg ||
395 k == ConversionSpecifier::FreeBSDDArg)
396 argIndex++;
398 if (k == ConversionSpecifier::InvalidSpecifier) {
399 unsigned Len = I - Start;
400 if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
401 CS.setEndScanList(Start + Len);
402 FS.setConversionSpecifier(CS);
404 // Assume the conversion takes one argument.
405 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
407 return PrintfSpecifierResult(Start, FS);
410 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
411 const char *I,
412 const char *E,
413 const LangOptions &LO,
414 const TargetInfo &Target,
415 bool isFreeBSDKPrintf) {
417 unsigned argIndex = 0;
419 // Keep looking for a format specifier until we have exhausted the string.
420 while (I != E) {
421 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
422 LO, Target, true,
423 isFreeBSDKPrintf);
424 // Did a fail-stop error of any kind occur when parsing the specifier?
425 // If so, don't do any more processing.
426 if (FSR.shouldStop())
427 return true;
428 // Did we exhaust the string or encounter an error that
429 // we can recover from?
430 if (!FSR.hasValue())
431 continue;
432 // We have a format specifier. Pass it to the callback.
433 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
434 I - FSR.getStart(), Target))
435 return true;
437 assert(I == E && "Format string not exhausted");
438 return false;
441 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
442 const char *E,
443 const LangOptions &LO,
444 const TargetInfo &Target) {
446 unsigned argIndex = 0;
448 // Keep looking for a %s format specifier until we have exhausted the string.
449 FormatStringHandler H;
450 while (I != E) {
451 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
452 LO, Target, false,
453 false);
454 // Did a fail-stop error of any kind occur when parsing the specifier?
455 // If so, don't do any more processing.
456 if (FSR.shouldStop())
457 return false;
458 // Did we exhaust the string or encounter an error that
459 // we can recover from?
460 if (!FSR.hasValue())
461 continue;
462 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
463 // Return true if this a %s format specifier.
464 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
465 return true;
467 return false;
470 bool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers(
471 const char *Begin, const char *End, const LangOptions &LO,
472 const TargetInfo &Target) {
473 unsigned ArgIndex = 0;
474 // Keep looking for a formatting specifier until we have exhausted the string.
475 FormatStringHandler H;
476 while (Begin != End) {
477 const PrintfSpecifierResult &FSR =
478 ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
479 if (FSR.shouldStop())
480 break;
481 if (FSR.hasValue())
482 return true;
484 return false;
487 //===----------------------------------------------------------------------===//
488 // Methods on PrintfSpecifier.
489 //===----------------------------------------------------------------------===//
491 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
492 bool IsObjCLiteral) const {
493 if (CS.getKind() == ConversionSpecifier::cArg)
494 switch (LM.getKind()) {
495 case LengthModifier::None:
496 return Ctx.IntTy;
497 case LengthModifier::AsLong:
498 case LengthModifier::AsWide:
499 return ArgType(ArgType::WIntTy, "wint_t");
500 case LengthModifier::AsShort:
501 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
502 return Ctx.IntTy;
503 [[fallthrough]];
504 default:
505 return ArgType::Invalid();
508 if (CS.isIntArg())
509 switch (LM.getKind()) {
510 case LengthModifier::AsLongDouble:
511 // GNU extension.
512 return Ctx.LongLongTy;
513 case LengthModifier::None:
514 case LengthModifier::AsShortLong:
515 return Ctx.IntTy;
516 case LengthModifier::AsInt32:
517 return ArgType(Ctx.IntTy, "__int32");
518 case LengthModifier::AsChar:
519 return ArgType::AnyCharTy;
520 case LengthModifier::AsShort: return Ctx.ShortTy;
521 case LengthModifier::AsLong: return Ctx.LongTy;
522 case LengthModifier::AsLongLong:
523 case LengthModifier::AsQuad:
524 return Ctx.LongLongTy;
525 case LengthModifier::AsInt64:
526 return ArgType(Ctx.LongLongTy, "__int64");
527 case LengthModifier::AsIntMax:
528 return ArgType(Ctx.getIntMaxType(), "intmax_t");
529 case LengthModifier::AsSizeT:
530 return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
531 case LengthModifier::AsInt3264:
532 return Ctx.getTargetInfo().getTriple().isArch64Bit()
533 ? ArgType(Ctx.LongLongTy, "__int64")
534 : ArgType(Ctx.IntTy, "__int32");
535 case LengthModifier::AsPtrDiff:
536 return ArgType::makePtrdiffT(
537 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
538 case LengthModifier::AsAllocate:
539 case LengthModifier::AsMAllocate:
540 case LengthModifier::AsWide:
541 return ArgType::Invalid();
544 if (CS.isUIntArg())
545 switch (LM.getKind()) {
546 case LengthModifier::AsLongDouble:
547 // GNU extension.
548 return Ctx.UnsignedLongLongTy;
549 case LengthModifier::None:
550 case LengthModifier::AsShortLong:
551 return Ctx.UnsignedIntTy;
552 case LengthModifier::AsInt32:
553 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
554 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
555 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
556 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
557 case LengthModifier::AsLongLong:
558 case LengthModifier::AsQuad:
559 return Ctx.UnsignedLongLongTy;
560 case LengthModifier::AsInt64:
561 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
562 case LengthModifier::AsIntMax:
563 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
564 case LengthModifier::AsSizeT:
565 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
566 case LengthModifier::AsInt3264:
567 return Ctx.getTargetInfo().getTriple().isArch64Bit()
568 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
569 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
570 case LengthModifier::AsPtrDiff:
571 return ArgType::makePtrdiffT(
572 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
573 case LengthModifier::AsAllocate:
574 case LengthModifier::AsMAllocate:
575 case LengthModifier::AsWide:
576 return ArgType::Invalid();
579 if (CS.isDoubleArg()) {
580 if (!VectorNumElts.isInvalid()) {
581 switch (LM.getKind()) {
582 case LengthModifier::AsShort:
583 return Ctx.HalfTy;
584 case LengthModifier::AsShortLong:
585 return Ctx.FloatTy;
586 case LengthModifier::AsLong:
587 default:
588 return Ctx.DoubleTy;
592 if (LM.getKind() == LengthModifier::AsLongDouble)
593 return Ctx.LongDoubleTy;
594 return Ctx.DoubleTy;
597 if (CS.getKind() == ConversionSpecifier::nArg) {
598 switch (LM.getKind()) {
599 case LengthModifier::None:
600 return ArgType::PtrTo(Ctx.IntTy);
601 case LengthModifier::AsChar:
602 return ArgType::PtrTo(Ctx.SignedCharTy);
603 case LengthModifier::AsShort:
604 return ArgType::PtrTo(Ctx.ShortTy);
605 case LengthModifier::AsLong:
606 return ArgType::PtrTo(Ctx.LongTy);
607 case LengthModifier::AsLongLong:
608 case LengthModifier::AsQuad:
609 return ArgType::PtrTo(Ctx.LongLongTy);
610 case LengthModifier::AsIntMax:
611 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
612 case LengthModifier::AsSizeT:
613 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
614 case LengthModifier::AsPtrDiff:
615 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
616 case LengthModifier::AsLongDouble:
617 return ArgType(); // FIXME: Is this a known extension?
618 case LengthModifier::AsAllocate:
619 case LengthModifier::AsMAllocate:
620 case LengthModifier::AsInt32:
621 case LengthModifier::AsInt3264:
622 case LengthModifier::AsInt64:
623 case LengthModifier::AsWide:
624 return ArgType::Invalid();
625 case LengthModifier::AsShortLong:
626 llvm_unreachable("only used for OpenCL which doesn not handle nArg");
630 switch (CS.getKind()) {
631 case ConversionSpecifier::sArg:
632 if (LM.getKind() == LengthModifier::AsWideChar) {
633 if (IsObjCLiteral)
634 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
635 "const unichar *");
636 return ArgType(ArgType::WCStrTy, "wchar_t *");
638 if (LM.getKind() == LengthModifier::AsWide)
639 return ArgType(ArgType::WCStrTy, "wchar_t *");
640 return ArgType::CStrTy;
641 case ConversionSpecifier::SArg:
642 if (IsObjCLiteral)
643 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
644 "const unichar *");
645 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
646 LM.getKind() == LengthModifier::AsShort)
647 return ArgType::CStrTy;
648 return ArgType(ArgType::WCStrTy, "wchar_t *");
649 case ConversionSpecifier::CArg:
650 if (IsObjCLiteral)
651 return ArgType(Ctx.UnsignedShortTy, "unichar");
652 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
653 LM.getKind() == LengthModifier::AsShort)
654 return Ctx.IntTy;
655 return ArgType(Ctx.WideCharTy, "wchar_t");
656 case ConversionSpecifier::pArg:
657 case ConversionSpecifier::PArg:
658 return ArgType::CPointerTy;
659 case ConversionSpecifier::ObjCObjArg:
660 return ArgType::ObjCPointerTy;
661 default:
662 break;
665 // FIXME: Handle other cases.
666 return ArgType();
670 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
671 bool IsObjCLiteral) const {
672 const PrintfConversionSpecifier &CS = getConversionSpecifier();
674 if (!CS.consumesDataArgument())
675 return ArgType::Invalid();
677 ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
678 if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
679 return ScalarTy;
681 return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
684 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
685 ASTContext &Ctx, bool IsObjCLiteral) {
686 // %n is different from other conversion specifiers; don't try to fix it.
687 if (CS.getKind() == ConversionSpecifier::nArg)
688 return false;
690 // Handle Objective-C objects first. Note that while the '%@' specifier will
691 // not warn for structure pointer or void pointer arguments (because that's
692 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
693 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
694 if (QT->isObjCRetainableType()) {
695 if (!IsObjCLiteral)
696 return false;
698 CS.setKind(ConversionSpecifier::ObjCObjArg);
700 // Disable irrelevant flags
701 HasThousandsGrouping = false;
702 HasPlusPrefix = false;
703 HasSpacePrefix = false;
704 HasAlternativeForm = false;
705 HasLeadingZeroes = false;
706 Precision.setHowSpecified(OptionalAmount::NotSpecified);
707 LM.setKind(LengthModifier::None);
709 return true;
712 // Handle strings next (char *, wchar_t *)
713 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
714 CS.setKind(ConversionSpecifier::sArg);
716 // Disable irrelevant flags
717 HasAlternativeForm = false;
718 HasLeadingZeroes = false;
720 // Set the long length modifier for wide characters
721 if (QT->getPointeeType()->isWideCharType())
722 LM.setKind(LengthModifier::AsWideChar);
723 else
724 LM.setKind(LengthModifier::None);
726 return true;
729 // If it's an enum, get its underlying type.
730 if (const EnumType *ETy = QT->getAs<EnumType>())
731 QT = ETy->getDecl()->getIntegerType();
733 const BuiltinType *BT = QT->getAs<BuiltinType>();
734 if (!BT) {
735 const VectorType *VT = QT->getAs<VectorType>();
736 if (VT) {
737 QT = VT->getElementType();
738 BT = QT->getAs<BuiltinType>();
739 VectorNumElts = OptionalAmount(VT->getNumElements());
743 // We can only work with builtin types.
744 if (!BT)
745 return false;
747 // Set length modifier
748 switch (BT->getKind()) {
749 case BuiltinType::Bool:
750 case BuiltinType::WChar_U:
751 case BuiltinType::WChar_S:
752 case BuiltinType::Char8: // FIXME: Treat like 'char'?
753 case BuiltinType::Char16:
754 case BuiltinType::Char32:
755 case BuiltinType::UInt128:
756 case BuiltinType::Int128:
757 case BuiltinType::Half:
758 case BuiltinType::BFloat16:
759 case BuiltinType::Float16:
760 case BuiltinType::Float128:
761 case BuiltinType::Ibm128:
762 case BuiltinType::ShortAccum:
763 case BuiltinType::Accum:
764 case BuiltinType::LongAccum:
765 case BuiltinType::UShortAccum:
766 case BuiltinType::UAccum:
767 case BuiltinType::ULongAccum:
768 case BuiltinType::ShortFract:
769 case BuiltinType::Fract:
770 case BuiltinType::LongFract:
771 case BuiltinType::UShortFract:
772 case BuiltinType::UFract:
773 case BuiltinType::ULongFract:
774 case BuiltinType::SatShortAccum:
775 case BuiltinType::SatAccum:
776 case BuiltinType::SatLongAccum:
777 case BuiltinType::SatUShortAccum:
778 case BuiltinType::SatUAccum:
779 case BuiltinType::SatULongAccum:
780 case BuiltinType::SatShortFract:
781 case BuiltinType::SatFract:
782 case BuiltinType::SatLongFract:
783 case BuiltinType::SatUShortFract:
784 case BuiltinType::SatUFract:
785 case BuiltinType::SatULongFract:
786 // Various types which are non-trivial to correct.
787 return false;
789 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
790 case BuiltinType::Id:
791 #include "clang/Basic/OpenCLImageTypes.def"
792 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
793 case BuiltinType::Id:
794 #include "clang/Basic/OpenCLExtensionTypes.def"
795 #define SVE_TYPE(Name, Id, SingletonId) \
796 case BuiltinType::Id:
797 #include "clang/Basic/AArch64SVEACLETypes.def"
798 #define PPC_VECTOR_TYPE(Name, Id, Size) \
799 case BuiltinType::Id:
800 #include "clang/Basic/PPCTypes.def"
801 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
802 #include "clang/Basic/RISCVVTypes.def"
803 #define SIGNED_TYPE(Id, SingletonId)
804 #define UNSIGNED_TYPE(Id, SingletonId)
805 #define FLOATING_TYPE(Id, SingletonId)
806 #define BUILTIN_TYPE(Id, SingletonId) \
807 case BuiltinType::Id:
808 #include "clang/AST/BuiltinTypes.def"
809 // Misc other stuff which doesn't make sense here.
810 return false;
812 case BuiltinType::UInt:
813 case BuiltinType::Int:
814 case BuiltinType::Float:
815 LM.setKind(VectorNumElts.isInvalid() ?
816 LengthModifier::None : LengthModifier::AsShortLong);
817 break;
818 case BuiltinType::Double:
819 LM.setKind(VectorNumElts.isInvalid() ?
820 LengthModifier::None : LengthModifier::AsLong);
821 break;
822 case BuiltinType::Char_U:
823 case BuiltinType::UChar:
824 case BuiltinType::Char_S:
825 case BuiltinType::SChar:
826 LM.setKind(LengthModifier::AsChar);
827 break;
829 case BuiltinType::Short:
830 case BuiltinType::UShort:
831 LM.setKind(LengthModifier::AsShort);
832 break;
834 case BuiltinType::Long:
835 case BuiltinType::ULong:
836 LM.setKind(LengthModifier::AsLong);
837 break;
839 case BuiltinType::LongLong:
840 case BuiltinType::ULongLong:
841 LM.setKind(LengthModifier::AsLongLong);
842 break;
844 case BuiltinType::LongDouble:
845 LM.setKind(LengthModifier::AsLongDouble);
846 break;
849 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
850 if (LangOpt.C99 || LangOpt.CPlusPlus11)
851 namedTypeToLengthModifier(QT, LM);
853 // If fixing the length modifier was enough, we might be done.
854 if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
855 // If we're going to offer a fix anyway, make sure the sign matches.
856 switch (CS.getKind()) {
857 case ConversionSpecifier::uArg:
858 case ConversionSpecifier::UArg:
859 if (QT->isSignedIntegerType())
860 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
861 break;
862 case ConversionSpecifier::dArg:
863 case ConversionSpecifier::DArg:
864 case ConversionSpecifier::iArg:
865 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
866 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
867 break;
868 default:
869 // Other specifiers do not have signed/unsigned variants.
870 break;
873 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
874 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
875 return true;
878 // Set conversion specifier and disable any flags which do not apply to it.
879 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
880 if (!QT->getAs<TypedefType>() && QT->isCharType()) {
881 CS.setKind(ConversionSpecifier::cArg);
882 LM.setKind(LengthModifier::None);
883 Precision.setHowSpecified(OptionalAmount::NotSpecified);
884 HasAlternativeForm = false;
885 HasLeadingZeroes = false;
886 HasPlusPrefix = false;
888 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
889 else if (QT->isRealFloatingType()) {
890 CS.setKind(ConversionSpecifier::fArg);
891 } else if (QT->isSignedIntegerType()) {
892 CS.setKind(ConversionSpecifier::dArg);
893 HasAlternativeForm = false;
894 } else if (QT->isUnsignedIntegerType()) {
895 CS.setKind(ConversionSpecifier::uArg);
896 HasAlternativeForm = false;
897 HasPlusPrefix = false;
898 } else {
899 llvm_unreachable("Unexpected type");
902 return true;
905 void PrintfSpecifier::toString(raw_ostream &os) const {
906 // Whilst some features have no defined order, we are using the order
907 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
908 os << "%";
910 // Positional args
911 if (usesPositionalArg()) {
912 os << getPositionalArgIndex() << "$";
915 // Conversion flags
916 if (IsLeftJustified) os << "-";
917 if (HasPlusPrefix) os << "+";
918 if (HasSpacePrefix) os << " ";
919 if (HasAlternativeForm) os << "#";
920 if (HasLeadingZeroes) os << "0";
922 // Minimum field width
923 FieldWidth.toString(os);
924 // Precision
925 Precision.toString(os);
927 // Vector modifier
928 if (!VectorNumElts.isInvalid())
929 os << 'v' << VectorNumElts.getConstantAmount();
931 // Length modifier
932 os << LM.toString();
933 // Conversion specifier
934 os << CS.toString();
937 bool PrintfSpecifier::hasValidPlusPrefix() const {
938 if (!HasPlusPrefix)
939 return true;
941 // The plus prefix only makes sense for signed conversions
942 switch (CS.getKind()) {
943 case ConversionSpecifier::dArg:
944 case ConversionSpecifier::DArg:
945 case ConversionSpecifier::iArg:
946 case ConversionSpecifier::fArg:
947 case ConversionSpecifier::FArg:
948 case ConversionSpecifier::eArg:
949 case ConversionSpecifier::EArg:
950 case ConversionSpecifier::gArg:
951 case ConversionSpecifier::GArg:
952 case ConversionSpecifier::aArg:
953 case ConversionSpecifier::AArg:
954 case ConversionSpecifier::FreeBSDrArg:
955 case ConversionSpecifier::FreeBSDyArg:
956 return true;
958 default:
959 return false;
963 bool PrintfSpecifier::hasValidAlternativeForm() const {
964 if (!HasAlternativeForm)
965 return true;
967 // Alternate form flag only valid with the bBoxXaAeEfFgG conversions
968 switch (CS.getKind()) {
969 case ConversionSpecifier::bArg:
970 case ConversionSpecifier::BArg:
971 case ConversionSpecifier::oArg:
972 case ConversionSpecifier::OArg:
973 case ConversionSpecifier::xArg:
974 case ConversionSpecifier::XArg:
975 case ConversionSpecifier::aArg:
976 case ConversionSpecifier::AArg:
977 case ConversionSpecifier::eArg:
978 case ConversionSpecifier::EArg:
979 case ConversionSpecifier::fArg:
980 case ConversionSpecifier::FArg:
981 case ConversionSpecifier::gArg:
982 case ConversionSpecifier::GArg:
983 case ConversionSpecifier::FreeBSDrArg:
984 case ConversionSpecifier::FreeBSDyArg:
985 return true;
987 default:
988 return false;
992 bool PrintfSpecifier::hasValidLeadingZeros() const {
993 if (!HasLeadingZeroes)
994 return true;
996 // Leading zeroes flag only valid with the bBdiouxXaAeEfFgG conversions
997 switch (CS.getKind()) {
998 case ConversionSpecifier::bArg:
999 case ConversionSpecifier::BArg:
1000 case ConversionSpecifier::dArg:
1001 case ConversionSpecifier::DArg:
1002 case ConversionSpecifier::iArg:
1003 case ConversionSpecifier::oArg:
1004 case ConversionSpecifier::OArg:
1005 case ConversionSpecifier::uArg:
1006 case ConversionSpecifier::UArg:
1007 case ConversionSpecifier::xArg:
1008 case ConversionSpecifier::XArg:
1009 case ConversionSpecifier::aArg:
1010 case ConversionSpecifier::AArg:
1011 case ConversionSpecifier::eArg:
1012 case ConversionSpecifier::EArg:
1013 case ConversionSpecifier::fArg:
1014 case ConversionSpecifier::FArg:
1015 case ConversionSpecifier::gArg:
1016 case ConversionSpecifier::GArg:
1017 case ConversionSpecifier::FreeBSDrArg:
1018 case ConversionSpecifier::FreeBSDyArg:
1019 return true;
1021 default:
1022 return false;
1026 bool PrintfSpecifier::hasValidSpacePrefix() const {
1027 if (!HasSpacePrefix)
1028 return true;
1030 // The space prefix only makes sense for signed conversions
1031 switch (CS.getKind()) {
1032 case ConversionSpecifier::dArg:
1033 case ConversionSpecifier::DArg:
1034 case ConversionSpecifier::iArg:
1035 case ConversionSpecifier::fArg:
1036 case ConversionSpecifier::FArg:
1037 case ConversionSpecifier::eArg:
1038 case ConversionSpecifier::EArg:
1039 case ConversionSpecifier::gArg:
1040 case ConversionSpecifier::GArg:
1041 case ConversionSpecifier::aArg:
1042 case ConversionSpecifier::AArg:
1043 case ConversionSpecifier::FreeBSDrArg:
1044 case ConversionSpecifier::FreeBSDyArg:
1045 return true;
1047 default:
1048 return false;
1052 bool PrintfSpecifier::hasValidLeftJustified() const {
1053 if (!IsLeftJustified)
1054 return true;
1056 // The left justified flag is valid for all conversions except n
1057 switch (CS.getKind()) {
1058 case ConversionSpecifier::nArg:
1059 return false;
1061 default:
1062 return true;
1066 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1067 if (!HasThousandsGrouping)
1068 return true;
1070 switch (CS.getKind()) {
1071 case ConversionSpecifier::dArg:
1072 case ConversionSpecifier::DArg:
1073 case ConversionSpecifier::iArg:
1074 case ConversionSpecifier::uArg:
1075 case ConversionSpecifier::UArg:
1076 case ConversionSpecifier::fArg:
1077 case ConversionSpecifier::FArg:
1078 case ConversionSpecifier::gArg:
1079 case ConversionSpecifier::GArg:
1080 return true;
1081 default:
1082 return false;
1086 bool PrintfSpecifier::hasValidPrecision() const {
1087 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1088 return true;
1090 // Precision is only valid with the bBdiouxXaAeEfFgGsP conversions
1091 switch (CS.getKind()) {
1092 case ConversionSpecifier::bArg:
1093 case ConversionSpecifier::BArg:
1094 case ConversionSpecifier::dArg:
1095 case ConversionSpecifier::DArg:
1096 case ConversionSpecifier::iArg:
1097 case ConversionSpecifier::oArg:
1098 case ConversionSpecifier::OArg:
1099 case ConversionSpecifier::uArg:
1100 case ConversionSpecifier::UArg:
1101 case ConversionSpecifier::xArg:
1102 case ConversionSpecifier::XArg:
1103 case ConversionSpecifier::aArg:
1104 case ConversionSpecifier::AArg:
1105 case ConversionSpecifier::eArg:
1106 case ConversionSpecifier::EArg:
1107 case ConversionSpecifier::fArg:
1108 case ConversionSpecifier::FArg:
1109 case ConversionSpecifier::gArg:
1110 case ConversionSpecifier::GArg:
1111 case ConversionSpecifier::sArg:
1112 case ConversionSpecifier::FreeBSDrArg:
1113 case ConversionSpecifier::FreeBSDyArg:
1114 case ConversionSpecifier::PArg:
1115 return true;
1117 default:
1118 return false;
1121 bool PrintfSpecifier::hasValidFieldWidth() const {
1122 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1123 return true;
1125 // The field width is valid for all conversions except n
1126 switch (CS.getKind()) {
1127 case ConversionSpecifier::nArg:
1128 return false;
1130 default:
1131 return true;