13d1dcd9bSDimitry Andric // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
23d1dcd9bSDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d1dcd9bSDimitry Andric //
73d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
83d1dcd9bSDimitry Andric //
93d1dcd9bSDimitry Andric // Shared details for processing format strings of printf and scanf
103d1dcd9bSDimitry Andric // (and friends).
113d1dcd9bSDimitry Andric //
123d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
133d1dcd9bSDimitry Andric
143d1dcd9bSDimitry Andric #include "FormatStringParsing.h"
15dbe13110SDimitry Andric #include "clang/Basic/LangOptions.h"
1613cc256eSDimitry Andric #include "clang/Basic/TargetInfo.h"
172b6b257fSDimitry Andric #include "llvm/Support/ConvertUTF.h"
18e3b55780SDimitry Andric #include <optional>
193d1dcd9bSDimitry Andric
2056d91b49SDimitry Andric using clang::analyze_format_string::ArgType;
213d1dcd9bSDimitry Andric using clang::analyze_format_string::FormatStringHandler;
223d1dcd9bSDimitry Andric using clang::analyze_format_string::FormatSpecifier;
233d1dcd9bSDimitry Andric using clang::analyze_format_string::LengthModifier;
243d1dcd9bSDimitry Andric using clang::analyze_format_string::OptionalAmount;
253d1dcd9bSDimitry Andric using clang::analyze_format_string::ConversionSpecifier;
263d1dcd9bSDimitry Andric using namespace clang;
273d1dcd9bSDimitry Andric
283d1dcd9bSDimitry Andric // Key function to FormatStringHandler.
~FormatStringHandler()293d1dcd9bSDimitry Andric FormatStringHandler::~FormatStringHandler() {}
303d1dcd9bSDimitry Andric
313d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
323d1dcd9bSDimitry Andric // Functions for parsing format strings components in both printf and
333d1dcd9bSDimitry Andric // scanf format strings.
343d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
353d1dcd9bSDimitry Andric
363d1dcd9bSDimitry Andric OptionalAmount
ParseAmount(const char * & Beg,const char * E)373d1dcd9bSDimitry Andric clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
383d1dcd9bSDimitry Andric const char *I = Beg;
393d1dcd9bSDimitry Andric UpdateOnReturn <const char*> UpdateBeg(Beg, I);
403d1dcd9bSDimitry Andric
413d1dcd9bSDimitry Andric unsigned accumulator = 0;
423d1dcd9bSDimitry Andric bool hasDigits = false;
433d1dcd9bSDimitry Andric
443d1dcd9bSDimitry Andric for ( ; I != E; ++I) {
453d1dcd9bSDimitry Andric char c = *I;
463d1dcd9bSDimitry Andric if (c >= '0' && c <= '9') {
473d1dcd9bSDimitry Andric hasDigits = true;
483d1dcd9bSDimitry Andric accumulator = (accumulator * 10) + (c - '0');
493d1dcd9bSDimitry Andric continue;
503d1dcd9bSDimitry Andric }
513d1dcd9bSDimitry Andric
523d1dcd9bSDimitry Andric if (hasDigits)
533d1dcd9bSDimitry Andric return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
543d1dcd9bSDimitry Andric false);
553d1dcd9bSDimitry Andric
563d1dcd9bSDimitry Andric break;
573d1dcd9bSDimitry Andric }
583d1dcd9bSDimitry Andric
593d1dcd9bSDimitry Andric return OptionalAmount();
603d1dcd9bSDimitry Andric }
613d1dcd9bSDimitry Andric
623d1dcd9bSDimitry Andric OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)633d1dcd9bSDimitry Andric clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
643d1dcd9bSDimitry Andric const char *E,
653d1dcd9bSDimitry Andric unsigned &argIndex) {
663d1dcd9bSDimitry Andric if (*Beg == '*') {
673d1dcd9bSDimitry Andric ++Beg;
683d1dcd9bSDimitry Andric return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
693d1dcd9bSDimitry Andric }
703d1dcd9bSDimitry Andric
713d1dcd9bSDimitry Andric return ParseAmount(Beg, E);
723d1dcd9bSDimitry Andric }
733d1dcd9bSDimitry Andric
743d1dcd9bSDimitry Andric OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)753d1dcd9bSDimitry Andric clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
763d1dcd9bSDimitry Andric const char *Start,
773d1dcd9bSDimitry Andric const char *&Beg,
783d1dcd9bSDimitry Andric const char *E,
793d1dcd9bSDimitry Andric PositionContext p) {
803d1dcd9bSDimitry Andric if (*Beg == '*') {
813d1dcd9bSDimitry Andric const char *I = Beg + 1;
823d1dcd9bSDimitry Andric const OptionalAmount &Amt = ParseAmount(I, E);
833d1dcd9bSDimitry Andric
843d1dcd9bSDimitry Andric if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
853d1dcd9bSDimitry Andric H.HandleInvalidPosition(Beg, I - Beg, p);
863d1dcd9bSDimitry Andric return OptionalAmount(false);
873d1dcd9bSDimitry Andric }
883d1dcd9bSDimitry Andric
893d1dcd9bSDimitry Andric if (I == E) {
903d1dcd9bSDimitry Andric // No more characters left?
913d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
923d1dcd9bSDimitry Andric return OptionalAmount(false);
933d1dcd9bSDimitry Andric }
943d1dcd9bSDimitry Andric
953d1dcd9bSDimitry Andric assert(Amt.getHowSpecified() == OptionalAmount::Constant);
963d1dcd9bSDimitry Andric
973d1dcd9bSDimitry Andric if (*I == '$') {
983d1dcd9bSDimitry Andric // Handle positional arguments
993d1dcd9bSDimitry Andric
1003d1dcd9bSDimitry Andric // Special case: '*0$', since this is an easy mistake.
1013d1dcd9bSDimitry Andric if (Amt.getConstantAmount() == 0) {
1023d1dcd9bSDimitry Andric H.HandleZeroPosition(Beg, I - Beg + 1);
1033d1dcd9bSDimitry Andric return OptionalAmount(false);
1043d1dcd9bSDimitry Andric }
1053d1dcd9bSDimitry Andric
1063d1dcd9bSDimitry Andric const char *Tmp = Beg;
1073d1dcd9bSDimitry Andric Beg = ++I;
1083d1dcd9bSDimitry Andric
1093d1dcd9bSDimitry Andric return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
1103d1dcd9bSDimitry Andric Tmp, 0, true);
1113d1dcd9bSDimitry Andric }
1123d1dcd9bSDimitry Andric
1133d1dcd9bSDimitry Andric H.HandleInvalidPosition(Beg, I - Beg, p);
1143d1dcd9bSDimitry Andric return OptionalAmount(false);
1153d1dcd9bSDimitry Andric }
1163d1dcd9bSDimitry Andric
1173d1dcd9bSDimitry Andric return ParseAmount(Beg, E);
1183d1dcd9bSDimitry Andric }
1193d1dcd9bSDimitry Andric
1203d1dcd9bSDimitry Andric
1213d1dcd9bSDimitry Andric bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)1223d1dcd9bSDimitry Andric clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
1233d1dcd9bSDimitry Andric FormatSpecifier &CS,
1243d1dcd9bSDimitry Andric const char *Start,
1253d1dcd9bSDimitry Andric const char *&Beg, const char *E,
1263d1dcd9bSDimitry Andric unsigned *argIndex) {
1273d1dcd9bSDimitry Andric // FIXME: Support negative field widths.
1283d1dcd9bSDimitry Andric if (argIndex) {
1293d1dcd9bSDimitry Andric CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
1303d1dcd9bSDimitry Andric }
1313d1dcd9bSDimitry Andric else {
1323d1dcd9bSDimitry Andric const OptionalAmount Amt =
1333d1dcd9bSDimitry Andric ParsePositionAmount(H, Start, Beg, E,
1343d1dcd9bSDimitry Andric analyze_format_string::FieldWidthPos);
1353d1dcd9bSDimitry Andric
1363d1dcd9bSDimitry Andric if (Amt.isInvalid())
1373d1dcd9bSDimitry Andric return true;
1383d1dcd9bSDimitry Andric CS.setFieldWidth(Amt);
1393d1dcd9bSDimitry Andric }
1403d1dcd9bSDimitry Andric return false;
1413d1dcd9bSDimitry Andric }
1423d1dcd9bSDimitry Andric
1433d1dcd9bSDimitry Andric bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)1443d1dcd9bSDimitry Andric clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
1453d1dcd9bSDimitry Andric FormatSpecifier &FS,
1463d1dcd9bSDimitry Andric const char *Start,
1473d1dcd9bSDimitry Andric const char *&Beg,
1483d1dcd9bSDimitry Andric const char *E) {
1493d1dcd9bSDimitry Andric const char *I = Beg;
1503d1dcd9bSDimitry Andric
1513d1dcd9bSDimitry Andric const OptionalAmount &Amt = ParseAmount(I, E);
1523d1dcd9bSDimitry Andric
1533d1dcd9bSDimitry Andric if (I == E) {
1543d1dcd9bSDimitry Andric // No more characters left?
1553d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1563d1dcd9bSDimitry Andric return true;
1573d1dcd9bSDimitry Andric }
1583d1dcd9bSDimitry Andric
1593d1dcd9bSDimitry Andric if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
160dbe13110SDimitry Andric // Warn that positional arguments are non-standard.
161dbe13110SDimitry Andric H.HandlePosition(Start, I - Start);
162dbe13110SDimitry Andric
1633d1dcd9bSDimitry Andric // Special case: '%0$', since this is an easy mistake.
1643d1dcd9bSDimitry Andric if (Amt.getConstantAmount() == 0) {
1653d1dcd9bSDimitry Andric H.HandleZeroPosition(Start, I - Start);
1663d1dcd9bSDimitry Andric return true;
1673d1dcd9bSDimitry Andric }
1683d1dcd9bSDimitry Andric
1693d1dcd9bSDimitry Andric FS.setArgIndex(Amt.getConstantAmount() - 1);
1703d1dcd9bSDimitry Andric FS.setUsesPositionalArg();
1713d1dcd9bSDimitry Andric // Update the caller's pointer if we decided to consume
1723d1dcd9bSDimitry Andric // these characters.
1733d1dcd9bSDimitry Andric Beg = I;
1743d1dcd9bSDimitry Andric return false;
1753d1dcd9bSDimitry Andric }
1763d1dcd9bSDimitry Andric
1773d1dcd9bSDimitry Andric return false;
1783d1dcd9bSDimitry Andric }
1793d1dcd9bSDimitry Andric
1803d1dcd9bSDimitry Andric bool
ParseVectorModifier(FormatStringHandler & H,FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO)181676fbe81SDimitry Andric clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
182676fbe81SDimitry Andric FormatSpecifier &FS,
183676fbe81SDimitry Andric const char *&I,
184676fbe81SDimitry Andric const char *E,
185676fbe81SDimitry Andric const LangOptions &LO) {
186676fbe81SDimitry Andric if (!LO.OpenCL)
187676fbe81SDimitry Andric return false;
188676fbe81SDimitry Andric
189676fbe81SDimitry Andric const char *Start = I;
190676fbe81SDimitry Andric if (*I == 'v') {
191676fbe81SDimitry Andric ++I;
192676fbe81SDimitry Andric
193676fbe81SDimitry Andric if (I == E) {
194676fbe81SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
195676fbe81SDimitry Andric return true;
196676fbe81SDimitry Andric }
197676fbe81SDimitry Andric
198676fbe81SDimitry Andric OptionalAmount NumElts = ParseAmount(I, E);
199676fbe81SDimitry Andric if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
200676fbe81SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
201676fbe81SDimitry Andric return true;
202676fbe81SDimitry Andric }
203676fbe81SDimitry Andric
204676fbe81SDimitry Andric FS.setVectorNumElts(NumElts);
205676fbe81SDimitry Andric }
206676fbe81SDimitry Andric
207676fbe81SDimitry Andric return false;
208676fbe81SDimitry Andric }
209676fbe81SDimitry Andric
210676fbe81SDimitry Andric bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)2113d1dcd9bSDimitry Andric clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
2123d1dcd9bSDimitry Andric const char *&I,
213dbe13110SDimitry Andric const char *E,
214dbe13110SDimitry Andric const LangOptions &LO,
215dbe13110SDimitry Andric bool IsScanf) {
2163d1dcd9bSDimitry Andric LengthModifier::Kind lmKind = LengthModifier::None;
2173d1dcd9bSDimitry Andric const char *lmPosition = I;
2183d1dcd9bSDimitry Andric switch (*I) {
2193d1dcd9bSDimitry Andric default:
2203d1dcd9bSDimitry Andric return false;
2213d1dcd9bSDimitry Andric case 'h':
2223d1dcd9bSDimitry Andric ++I;
2232b6b257fSDimitry Andric if (I != E && *I == 'h') {
2242b6b257fSDimitry Andric ++I;
2252b6b257fSDimitry Andric lmKind = LengthModifier::AsChar;
22622989816SDimitry Andric } else if (I != E && *I == 'l' && LO.OpenCL) {
22722989816SDimitry Andric ++I;
22822989816SDimitry Andric lmKind = LengthModifier::AsShortLong;
2292b6b257fSDimitry Andric } else {
2302b6b257fSDimitry Andric lmKind = LengthModifier::AsShort;
2312b6b257fSDimitry Andric }
2323d1dcd9bSDimitry Andric break;
2333d1dcd9bSDimitry Andric case 'l':
2343d1dcd9bSDimitry Andric ++I;
2352b6b257fSDimitry Andric if (I != E && *I == 'l') {
2362b6b257fSDimitry Andric ++I;
2372b6b257fSDimitry Andric lmKind = LengthModifier::AsLongLong;
2382b6b257fSDimitry Andric } else {
2392b6b257fSDimitry Andric lmKind = LengthModifier::AsLong;
2402b6b257fSDimitry Andric }
2413d1dcd9bSDimitry Andric break;
2423d1dcd9bSDimitry Andric case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
2433d1dcd9bSDimitry Andric case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
2443d1dcd9bSDimitry Andric case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
2453d1dcd9bSDimitry Andric case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
246dbe13110SDimitry Andric case 'q': lmKind = LengthModifier::AsQuad; ++I; break;
247dbe13110SDimitry Andric case 'a':
248809500fcSDimitry Andric if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
249dbe13110SDimitry Andric // For scanf in C90, look at the next character to see if this should
250dbe13110SDimitry Andric // be parsed as the GNU extension 'a' length modifier. If not, this
251dbe13110SDimitry Andric // will be parsed as a conversion specifier.
252dbe13110SDimitry Andric ++I;
253dbe13110SDimitry Andric if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
254dbe13110SDimitry Andric lmKind = LengthModifier::AsAllocate;
255dbe13110SDimitry Andric break;
256dbe13110SDimitry Andric }
257dbe13110SDimitry Andric --I;
258dbe13110SDimitry Andric }
259dbe13110SDimitry Andric return false;
260dbe13110SDimitry Andric case 'm':
261dbe13110SDimitry Andric if (IsScanf) {
262dbe13110SDimitry Andric lmKind = LengthModifier::AsMAllocate;
263dbe13110SDimitry Andric ++I;
264dbe13110SDimitry Andric break;
265dbe13110SDimitry Andric }
266dbe13110SDimitry Andric return false;
267bfef3995SDimitry Andric // printf: AsInt64, AsInt32, AsInt3264
268bfef3995SDimitry Andric // scanf: AsInt64
269bfef3995SDimitry Andric case 'I':
270bfef3995SDimitry Andric if (I + 1 != E && I + 2 != E) {
271bfef3995SDimitry Andric if (I[1] == '6' && I[2] == '4') {
272bfef3995SDimitry Andric I += 3;
273bfef3995SDimitry Andric lmKind = LengthModifier::AsInt64;
274bfef3995SDimitry Andric break;
275bfef3995SDimitry Andric }
276bfef3995SDimitry Andric if (IsScanf)
277bfef3995SDimitry Andric return false;
278bfef3995SDimitry Andric
279bfef3995SDimitry Andric if (I[1] == '3' && I[2] == '2') {
280bfef3995SDimitry Andric I += 3;
281bfef3995SDimitry Andric lmKind = LengthModifier::AsInt32;
282bfef3995SDimitry Andric break;
283bfef3995SDimitry Andric }
284bfef3995SDimitry Andric }
285bfef3995SDimitry Andric ++I;
286bfef3995SDimitry Andric lmKind = LengthModifier::AsInt3264;
287bfef3995SDimitry Andric break;
28806d4ba38SDimitry Andric case 'w':
28906d4ba38SDimitry Andric lmKind = LengthModifier::AsWide; ++I; break;
2903d1dcd9bSDimitry Andric }
2913d1dcd9bSDimitry Andric LengthModifier lm(lmPosition, lmKind);
2923d1dcd9bSDimitry Andric FS.setLengthModifier(lm);
2933d1dcd9bSDimitry Andric return true;
2943d1dcd9bSDimitry Andric }
2953d1dcd9bSDimitry Andric
ParseUTF8InvalidSpecifier(const char * SpecifierBegin,const char * FmtStrEnd,unsigned & Len)2962b6b257fSDimitry Andric bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
2972b6b257fSDimitry Andric const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
2982b6b257fSDimitry Andric if (SpecifierBegin + 1 >= FmtStrEnd)
2992b6b257fSDimitry Andric return false;
3002b6b257fSDimitry Andric
301bab175ecSDimitry Andric const llvm::UTF8 *SB =
302bab175ecSDimitry Andric reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
303bab175ecSDimitry Andric const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
3042b6b257fSDimitry Andric const char FirstByte = *SB;
3052b6b257fSDimitry Andric
3062b6b257fSDimitry Andric // If the invalid specifier is a multibyte UTF-8 string, return the
3072b6b257fSDimitry Andric // total length accordingly so that the conversion specifier can be
3082b6b257fSDimitry Andric // properly updated to reflect a complete UTF-8 specifier.
309bab175ecSDimitry Andric unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
3102b6b257fSDimitry Andric if (NumBytes == 1)
3112b6b257fSDimitry Andric return false;
3122b6b257fSDimitry Andric if (SB + NumBytes > SE)
3132b6b257fSDimitry Andric return false;
3142b6b257fSDimitry Andric
3152b6b257fSDimitry Andric Len = NumBytes + 1;
3162b6b257fSDimitry Andric return true;
3172b6b257fSDimitry Andric }
3182b6b257fSDimitry Andric
3193d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
32056d91b49SDimitry Andric // Methods on ArgType.
3213d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
3223d1dcd9bSDimitry Andric
3235e20cdd8SDimitry Andric clang::analyze_format_string::ArgType::MatchKind
matchesType(ASTContext & C,QualType argTy) const3245e20cdd8SDimitry Andric ArgType::matchesType(ASTContext &C, QualType argTy) const {
3251f917f69SDimitry Andric // When using the format attribute in C++, you can receive a function or an
3261f917f69SDimitry Andric // array that will necessarily decay to a pointer when passed to the final
3271f917f69SDimitry Andric // format consumer. Apply decay before type comparison.
3281f917f69SDimitry Andric if (argTy->canDecayToPointerType())
3291f917f69SDimitry Andric argTy = C.getDecayedType(argTy);
3301f917f69SDimitry Andric
33156d91b49SDimitry Andric if (Ptr) {
33256d91b49SDimitry Andric // It has to be a pointer.
33356d91b49SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>();
33456d91b49SDimitry Andric if (!PT)
3355e20cdd8SDimitry Andric return NoMatch;
33656d91b49SDimitry Andric
33756d91b49SDimitry Andric // We cannot write through a const qualified pointer.
33856d91b49SDimitry Andric if (PT->getPointeeType().isConstQualified())
3395e20cdd8SDimitry Andric return NoMatch;
34056d91b49SDimitry Andric
34156d91b49SDimitry Andric argTy = PT->getPointeeType();
34256d91b49SDimitry Andric }
34356d91b49SDimitry Andric
3443d1dcd9bSDimitry Andric switch (K) {
3453d1dcd9bSDimitry Andric case InvalidTy:
34656d91b49SDimitry Andric llvm_unreachable("ArgType must be valid");
3473d1dcd9bSDimitry Andric
3483d1dcd9bSDimitry Andric case UnknownTy:
3495e20cdd8SDimitry Andric return Match;
3503d1dcd9bSDimitry Andric
351dbe13110SDimitry Andric case AnyCharTy: {
352e3b55780SDimitry Andric if (const auto *ETy = argTy->getAs<EnumType>()) {
353bab175ecSDimitry Andric // If the enum is incomplete we know nothing about the underlying type.
3547fa27ce4SDimitry Andric // Assume that it's 'int'. Do not use the underlying type for a scoped
3557fa27ce4SDimitry Andric // enumeration.
356bab175ecSDimitry Andric if (!ETy->getDecl()->isComplete())
357bab175ecSDimitry Andric return NoMatch;
3587fa27ce4SDimitry Andric if (ETy->isUnscopedEnumerationType())
35956d91b49SDimitry Andric argTy = ETy->getDecl()->getIntegerType();
360bab175ecSDimitry Andric }
36156d91b49SDimitry Andric
362e3b55780SDimitry Andric if (const auto *BT = argTy->getAs<BuiltinType>()) {
363e3b55780SDimitry Andric // The types are perfectly matched?
364dbe13110SDimitry Andric switch (BT->getKind()) {
365dbe13110SDimitry Andric default:
366dbe13110SDimitry Andric break;
367dbe13110SDimitry Andric case BuiltinType::Char_S:
368dbe13110SDimitry Andric case BuiltinType::SChar:
369dbe13110SDimitry Andric case BuiltinType::UChar:
370dbe13110SDimitry Andric case BuiltinType::Char_U:
3715e20cdd8SDimitry Andric return Match;
372b1c73532SDimitry Andric case BuiltinType::Bool:
373b1c73532SDimitry Andric if (!Ptr)
374b1c73532SDimitry Andric return Match;
375b1c73532SDimitry Andric break;
376dbe13110SDimitry Andric }
377e3b55780SDimitry Andric // "Partially matched" because of promotions?
378e3b55780SDimitry Andric if (!Ptr) {
379e3b55780SDimitry Andric switch (BT->getKind()) {
380e3b55780SDimitry Andric default:
381e3b55780SDimitry Andric break;
382e3b55780SDimitry Andric case BuiltinType::Int:
383e3b55780SDimitry Andric case BuiltinType::UInt:
384e3b55780SDimitry Andric return MatchPromotion;
385e3b55780SDimitry Andric case BuiltinType::Short:
386e3b55780SDimitry Andric case BuiltinType::UShort:
387e3b55780SDimitry Andric case BuiltinType::WChar_S:
388e3b55780SDimitry Andric case BuiltinType::WChar_U:
389e3b55780SDimitry Andric return NoMatchPromotionTypeConfusion;
390e3b55780SDimitry Andric }
391e3b55780SDimitry Andric }
392e3b55780SDimitry Andric }
3935e20cdd8SDimitry Andric return NoMatch;
394dbe13110SDimitry Andric }
395dbe13110SDimitry Andric
3963d1dcd9bSDimitry Andric case SpecificTy: {
397bab175ecSDimitry Andric if (const EnumType *ETy = argTy->getAs<EnumType>()) {
398bab175ecSDimitry Andric // If the enum is incomplete we know nothing about the underlying type.
3997fa27ce4SDimitry Andric // Assume that it's 'int'. Do not use the underlying type for a scoped
4007fa27ce4SDimitry Andric // enumeration as that needs an exact match.
401bab175ecSDimitry Andric if (!ETy->getDecl()->isComplete())
402bab175ecSDimitry Andric argTy = C.IntTy;
4037fa27ce4SDimitry Andric else if (ETy->isUnscopedEnumerationType())
40456d91b49SDimitry Andric argTy = ETy->getDecl()->getIntegerType();
405bab175ecSDimitry Andric }
406ac9a064cSDimitry Andric
407ac9a064cSDimitry Andric if (argTy->isSaturatedFixedPointType())
408ac9a064cSDimitry Andric argTy = C.getCorrespondingUnsaturatedType(argTy);
409ac9a064cSDimitry Andric
4103d1dcd9bSDimitry Andric argTy = C.getCanonicalType(argTy).getUnqualifiedType();
41156d91b49SDimitry Andric
4123d1dcd9bSDimitry Andric if (T == argTy)
4135e20cdd8SDimitry Andric return Match;
414e3b55780SDimitry Andric if (const auto *BT = argTy->getAs<BuiltinType>()) {
415e3b55780SDimitry Andric // Check if the only difference between them is signed vs unsigned
416ac9a064cSDimitry Andric // if true, return match signedness.
4173d1dcd9bSDimitry Andric switch (BT->getKind()) {
4183d1dcd9bSDimitry Andric default:
4193d1dcd9bSDimitry Andric break;
420b1c73532SDimitry Andric case BuiltinType::Bool:
421b1c73532SDimitry Andric if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy))
422b1c73532SDimitry Andric return NoMatch;
423b1c73532SDimitry Andric [[fallthrough]];
4243d1dcd9bSDimitry Andric case BuiltinType::Char_S:
4253d1dcd9bSDimitry Andric case BuiltinType::SChar:
426ac9a064cSDimitry Andric if (T == C.UnsignedShortTy || T == C.ShortTy)
427ac9a064cSDimitry Andric return NoMatchTypeConfusion;
428ac9a064cSDimitry Andric if (T == C.UnsignedCharTy)
429ac9a064cSDimitry Andric return NoMatchSignedness;
430ac9a064cSDimitry Andric if (T == C.SignedCharTy)
431ac9a064cSDimitry Andric return Match;
432ac9a064cSDimitry Andric break;
4333d1dcd9bSDimitry Andric case BuiltinType::Char_U:
4343d1dcd9bSDimitry Andric case BuiltinType::UChar:
435519fc96cSDimitry Andric if (T == C.UnsignedShortTy || T == C.ShortTy)
436519fc96cSDimitry Andric return NoMatchTypeConfusion;
437ac9a064cSDimitry Andric if (T == C.UnsignedCharTy)
438e3b55780SDimitry Andric return Match;
439ac9a064cSDimitry Andric if (T == C.SignedCharTy)
440ac9a064cSDimitry Andric return NoMatchSignedness;
441e3b55780SDimitry Andric break;
4423d1dcd9bSDimitry Andric case BuiltinType::Short:
443e3b55780SDimitry Andric if (T == C.UnsignedShortTy)
444ac9a064cSDimitry Andric return NoMatchSignedness;
445e3b55780SDimitry Andric break;
4463d1dcd9bSDimitry Andric case BuiltinType::UShort:
447e3b55780SDimitry Andric if (T == C.ShortTy)
448ac9a064cSDimitry Andric return NoMatchSignedness;
449e3b55780SDimitry Andric break;
4503d1dcd9bSDimitry Andric case BuiltinType::Int:
451e3b55780SDimitry Andric if (T == C.UnsignedIntTy)
452ac9a064cSDimitry Andric return NoMatchSignedness;
453e3b55780SDimitry Andric break;
4543d1dcd9bSDimitry Andric case BuiltinType::UInt:
455e3b55780SDimitry Andric if (T == C.IntTy)
456ac9a064cSDimitry Andric return NoMatchSignedness;
457e3b55780SDimitry Andric break;
4583d1dcd9bSDimitry Andric case BuiltinType::Long:
459e3b55780SDimitry Andric if (T == C.UnsignedLongTy)
460ac9a064cSDimitry Andric return NoMatchSignedness;
461e3b55780SDimitry Andric break;
4623d1dcd9bSDimitry Andric case BuiltinType::ULong:
463e3b55780SDimitry Andric if (T == C.LongTy)
464ac9a064cSDimitry Andric return NoMatchSignedness;
465e3b55780SDimitry Andric break;
4663d1dcd9bSDimitry Andric case BuiltinType::LongLong:
467e3b55780SDimitry Andric if (T == C.UnsignedLongLongTy)
468ac9a064cSDimitry Andric return NoMatchSignedness;
469e3b55780SDimitry Andric break;
4703d1dcd9bSDimitry Andric case BuiltinType::ULongLong:
471e3b55780SDimitry Andric if (T == C.LongLongTy)
472ac9a064cSDimitry Andric return NoMatchSignedness;
473e3b55780SDimitry Andric break;
474e3b55780SDimitry Andric }
475e3b55780SDimitry Andric // "Partially matched" because of promotions?
476e3b55780SDimitry Andric if (!Ptr) {
477e3b55780SDimitry Andric switch (BT->getKind()) {
478e3b55780SDimitry Andric default:
479e3b55780SDimitry Andric break;
480b1c73532SDimitry Andric case BuiltinType::Bool:
481b1c73532SDimitry Andric if (T == C.IntTy || T == C.UnsignedIntTy)
482b1c73532SDimitry Andric return MatchPromotion;
483b1c73532SDimitry Andric break;
484e3b55780SDimitry Andric case BuiltinType::Int:
485e3b55780SDimitry Andric case BuiltinType::UInt:
486e3b55780SDimitry Andric if (T == C.SignedCharTy || T == C.UnsignedCharTy ||
487e3b55780SDimitry Andric T == C.ShortTy || T == C.UnsignedShortTy || T == C.WCharTy ||
488e3b55780SDimitry Andric T == C.WideCharTy)
489e3b55780SDimitry Andric return MatchPromotion;
490e3b55780SDimitry Andric break;
491b1c73532SDimitry Andric case BuiltinType::Char_U:
492b1c73532SDimitry Andric if (T == C.UnsignedIntTy)
493b1c73532SDimitry Andric return MatchPromotion;
494b1c73532SDimitry Andric if (T == C.UnsignedShortTy)
495b1c73532SDimitry Andric return NoMatchPromotionTypeConfusion;
496b1c73532SDimitry Andric break;
497b1c73532SDimitry Andric case BuiltinType::Char_S:
498b1c73532SDimitry Andric if (T == C.IntTy)
499b1c73532SDimitry Andric return MatchPromotion;
500b1c73532SDimitry Andric if (T == C.ShortTy)
501b1c73532SDimitry Andric return NoMatchPromotionTypeConfusion;
502b1c73532SDimitry Andric break;
503b1c73532SDimitry Andric case BuiltinType::Half:
504b1c73532SDimitry Andric case BuiltinType::Float:
505b1c73532SDimitry Andric if (T == C.DoubleTy)
506b1c73532SDimitry Andric return MatchPromotion;
507b1c73532SDimitry Andric break;
508e3b55780SDimitry Andric case BuiltinType::Short:
509e3b55780SDimitry Andric case BuiltinType::UShort:
510e3b55780SDimitry Andric if (T == C.SignedCharTy || T == C.UnsignedCharTy)
511e3b55780SDimitry Andric return NoMatchPromotionTypeConfusion;
512e3b55780SDimitry Andric break;
513e3b55780SDimitry Andric case BuiltinType::WChar_U:
514e3b55780SDimitry Andric case BuiltinType::WChar_S:
515e3b55780SDimitry Andric if (T != C.WCharTy && T != C.WideCharTy)
516e3b55780SDimitry Andric return NoMatchPromotionTypeConfusion;
517e3b55780SDimitry Andric }
518e3b55780SDimitry Andric }
5193d1dcd9bSDimitry Andric }
5205e20cdd8SDimitry Andric return NoMatch;
5213d1dcd9bSDimitry Andric }
5223d1dcd9bSDimitry Andric
5233d1dcd9bSDimitry Andric case CStrTy: {
5243d1dcd9bSDimitry Andric const PointerType *PT = argTy->getAs<PointerType>();
5253d1dcd9bSDimitry Andric if (!PT)
5265e20cdd8SDimitry Andric return NoMatch;
5273d1dcd9bSDimitry Andric QualType pointeeTy = PT->getPointeeType();
5283d1dcd9bSDimitry Andric if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
5293d1dcd9bSDimitry Andric switch (BT->getKind()) {
5303d1dcd9bSDimitry Andric case BuiltinType::Char_U:
5313d1dcd9bSDimitry Andric case BuiltinType::UChar:
5323d1dcd9bSDimitry Andric case BuiltinType::Char_S:
5333d1dcd9bSDimitry Andric case BuiltinType::SChar:
5345e20cdd8SDimitry Andric return Match;
5353d1dcd9bSDimitry Andric default:
5363d1dcd9bSDimitry Andric break;
5373d1dcd9bSDimitry Andric }
5383d1dcd9bSDimitry Andric
5395e20cdd8SDimitry Andric return NoMatch;
5403d1dcd9bSDimitry Andric }
5413d1dcd9bSDimitry Andric
5423d1dcd9bSDimitry Andric case WCStrTy: {
5433d1dcd9bSDimitry Andric const PointerType *PT = argTy->getAs<PointerType>();
5443d1dcd9bSDimitry Andric if (!PT)
5455e20cdd8SDimitry Andric return NoMatch;
5463d1dcd9bSDimitry Andric QualType pointeeTy =
5473d1dcd9bSDimitry Andric C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
5485e20cdd8SDimitry Andric return pointeeTy == C.getWideCharType() ? Match : NoMatch;
5493d1dcd9bSDimitry Andric }
5503d1dcd9bSDimitry Andric
5513d1dcd9bSDimitry Andric case WIntTy: {
55256d91b49SDimitry Andric QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
553676fbe81SDimitry Andric
554676fbe81SDimitry Andric if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
555676fbe81SDimitry Andric return Match;
556676fbe81SDimitry Andric
557e3b55780SDimitry Andric QualType PromoArg = C.isPromotableIntegerType(argTy)
558676fbe81SDimitry Andric ? C.getPromotedIntegerType(argTy)
559676fbe81SDimitry Andric : argTy;
5603d1dcd9bSDimitry Andric PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
5613d1dcd9bSDimitry Andric
56256d91b49SDimitry Andric // If the promoted argument is the corresponding signed type of the
56356d91b49SDimitry Andric // wint_t type, then it should match.
56456d91b49SDimitry Andric if (PromoArg->hasSignedIntegerRepresentation() &&
56556d91b49SDimitry Andric C.getCorrespondingUnsignedType(PromoArg) == WInt)
5665e20cdd8SDimitry Andric return Match;
56756d91b49SDimitry Andric
5685e20cdd8SDimitry Andric return WInt == PromoArg ? Match : NoMatch;
5693d1dcd9bSDimitry Andric }
5703d1dcd9bSDimitry Andric
5713d1dcd9bSDimitry Andric case CPointerTy:
5725e20cdd8SDimitry Andric if (argTy->isVoidPointerType()) {
5735e20cdd8SDimitry Andric return Match;
5745e20cdd8SDimitry Andric } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
5755e20cdd8SDimitry Andric argTy->isBlockPointerType() || argTy->isNullPtrType()) {
5765e20cdd8SDimitry Andric return NoMatchPedantic;
5775e20cdd8SDimitry Andric } else {
5785e20cdd8SDimitry Andric return NoMatch;
5795e20cdd8SDimitry Andric }
5803d1dcd9bSDimitry Andric
581dbe13110SDimitry Andric case ObjCPointerTy: {
582dbe13110SDimitry Andric if (argTy->getAs<ObjCObjectPointerType>() ||
583dbe13110SDimitry Andric argTy->getAs<BlockPointerType>())
5845e20cdd8SDimitry Andric return Match;
585dbe13110SDimitry Andric
586dbe13110SDimitry Andric // Handle implicit toll-free bridging.
587dbe13110SDimitry Andric if (const PointerType *PT = argTy->getAs<PointerType>()) {
588dbe13110SDimitry Andric // Things such as CFTypeRef are really just opaque pointers
589dbe13110SDimitry Andric // to C structs representing CF types that can often be bridged
590dbe13110SDimitry Andric // to Objective-C objects. Since the compiler doesn't know which
591dbe13110SDimitry Andric // structs can be toll-free bridged, we just accept them all.
592dbe13110SDimitry Andric QualType pointee = PT->getPointeeType();
593dbe13110SDimitry Andric if (pointee->getAsStructureType() || pointee->isVoidType())
5945e20cdd8SDimitry Andric return Match;
595dbe13110SDimitry Andric }
5965e20cdd8SDimitry Andric return NoMatch;
597dbe13110SDimitry Andric }
5983d1dcd9bSDimitry Andric }
5993d1dcd9bSDimitry Andric
60056d91b49SDimitry Andric llvm_unreachable("Invalid ArgType Kind!");
6013d1dcd9bSDimitry Andric }
6023d1dcd9bSDimitry Andric
makeVectorType(ASTContext & C,unsigned NumElts) const603676fbe81SDimitry Andric ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
60422989816SDimitry Andric // Check for valid vector element types.
60522989816SDimitry Andric if (T.isNull())
606676fbe81SDimitry Andric return ArgType::Invalid();
607676fbe81SDimitry Andric
608676fbe81SDimitry Andric QualType Vec = C.getExtVectorType(T, NumElts);
609676fbe81SDimitry Andric return ArgType(Vec, Name);
610676fbe81SDimitry Andric }
611676fbe81SDimitry Andric
getRepresentativeType(ASTContext & C) const61256d91b49SDimitry Andric QualType ArgType::getRepresentativeType(ASTContext &C) const {
61356d91b49SDimitry Andric QualType Res;
6143d1dcd9bSDimitry Andric switch (K) {
6153d1dcd9bSDimitry Andric case InvalidTy:
61656d91b49SDimitry Andric llvm_unreachable("No representative type for Invalid ArgType");
6173d1dcd9bSDimitry Andric case UnknownTy:
61856d91b49SDimitry Andric llvm_unreachable("No representative type for Unknown ArgType");
619dbe13110SDimitry Andric case AnyCharTy:
62056d91b49SDimitry Andric Res = C.CharTy;
62156d91b49SDimitry Andric break;
6223d1dcd9bSDimitry Andric case SpecificTy:
62356d91b49SDimitry Andric Res = T;
62456d91b49SDimitry Andric break;
6253d1dcd9bSDimitry Andric case CStrTy:
62656d91b49SDimitry Andric Res = C.getPointerType(C.CharTy);
62756d91b49SDimitry Andric break;
6283d1dcd9bSDimitry Andric case WCStrTy:
629bfef3995SDimitry Andric Res = C.getPointerType(C.getWideCharType());
63056d91b49SDimitry Andric break;
6313d1dcd9bSDimitry Andric case ObjCPointerTy:
63256d91b49SDimitry Andric Res = C.ObjCBuiltinIdTy;
63356d91b49SDimitry Andric break;
6343d1dcd9bSDimitry Andric case CPointerTy:
63556d91b49SDimitry Andric Res = C.VoidPtrTy;
63656d91b49SDimitry Andric break;
6373d1dcd9bSDimitry Andric case WIntTy: {
63856d91b49SDimitry Andric Res = C.getWIntType();
63956d91b49SDimitry Andric break;
6403d1dcd9bSDimitry Andric }
6413d1dcd9bSDimitry Andric }
6423d1dcd9bSDimitry Andric
64356d91b49SDimitry Andric if (Ptr)
64456d91b49SDimitry Andric Res = C.getPointerType(Res);
64556d91b49SDimitry Andric return Res;
6463d1dcd9bSDimitry Andric }
6473d1dcd9bSDimitry Andric
getRepresentativeTypeName(ASTContext & C) const64856d91b49SDimitry Andric std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
649cfca06d7SDimitry Andric std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
65056d91b49SDimitry Andric
65156d91b49SDimitry Andric std::string Alias;
65256d91b49SDimitry Andric if (Name) {
65356d91b49SDimitry Andric // Use a specific name for this type, e.g. "size_t".
65456d91b49SDimitry Andric Alias = Name;
65556d91b49SDimitry Andric if (Ptr) {
65656d91b49SDimitry Andric // If ArgType is actually a pointer to T, append an asterisk.
65756d91b49SDimitry Andric Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
65856d91b49SDimitry Andric }
65956d91b49SDimitry Andric // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
66056d91b49SDimitry Andric if (S == Alias)
66156d91b49SDimitry Andric Alias.clear();
66256d91b49SDimitry Andric }
66356d91b49SDimitry Andric
66456d91b49SDimitry Andric if (!Alias.empty())
66556d91b49SDimitry Andric return std::string("'") + Alias + "' (aka '" + S + "')";
666dbe13110SDimitry Andric return std::string("'") + S + "'";
667dbe13110SDimitry Andric }
668dbe13110SDimitry Andric
669dbe13110SDimitry Andric
6703d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
6713d1dcd9bSDimitry Andric // Methods on OptionalAmount.
6723d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
6733d1dcd9bSDimitry Andric
67456d91b49SDimitry Andric ArgType
getArgType(ASTContext & Ctx) const6753d1dcd9bSDimitry Andric analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
6763d1dcd9bSDimitry Andric return Ctx.IntTy;
6773d1dcd9bSDimitry Andric }
6783d1dcd9bSDimitry Andric
6793d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
6803d1dcd9bSDimitry Andric // Methods on LengthModifier.
6813d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
6823d1dcd9bSDimitry Andric
6833d1dcd9bSDimitry Andric const char *
toString() const6843d1dcd9bSDimitry Andric analyze_format_string::LengthModifier::toString() const {
6853d1dcd9bSDimitry Andric switch (kind) {
6863d1dcd9bSDimitry Andric case AsChar:
6873d1dcd9bSDimitry Andric return "hh";
6883d1dcd9bSDimitry Andric case AsShort:
6893d1dcd9bSDimitry Andric return "h";
69022989816SDimitry Andric case AsShortLong:
69122989816SDimitry Andric return "hl";
6923d1dcd9bSDimitry Andric case AsLong: // or AsWideChar
6933d1dcd9bSDimitry Andric return "l";
6943d1dcd9bSDimitry Andric case AsLongLong:
6953d1dcd9bSDimitry Andric return "ll";
696dbe13110SDimitry Andric case AsQuad:
697dbe13110SDimitry Andric return "q";
6983d1dcd9bSDimitry Andric case AsIntMax:
6993d1dcd9bSDimitry Andric return "j";
7003d1dcd9bSDimitry Andric case AsSizeT:
7013d1dcd9bSDimitry Andric return "z";
7023d1dcd9bSDimitry Andric case AsPtrDiff:
7033d1dcd9bSDimitry Andric return "t";
704bfef3995SDimitry Andric case AsInt32:
705bfef3995SDimitry Andric return "I32";
706bfef3995SDimitry Andric case AsInt3264:
707bfef3995SDimitry Andric return "I";
708bfef3995SDimitry Andric case AsInt64:
709bfef3995SDimitry Andric return "I64";
7103d1dcd9bSDimitry Andric case AsLongDouble:
7113d1dcd9bSDimitry Andric return "L";
712dbe13110SDimitry Andric case AsAllocate:
713dbe13110SDimitry Andric return "a";
714dbe13110SDimitry Andric case AsMAllocate:
715dbe13110SDimitry Andric return "m";
71606d4ba38SDimitry Andric case AsWide:
71706d4ba38SDimitry Andric return "w";
7183d1dcd9bSDimitry Andric case None:
7193d1dcd9bSDimitry Andric return "";
7203d1dcd9bSDimitry Andric }
7219f4dbff6SDimitry Andric return nullptr;
7223d1dcd9bSDimitry Andric }
7233d1dcd9bSDimitry Andric
7243d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
725dbe13110SDimitry Andric // Methods on ConversionSpecifier.
726dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
727dbe13110SDimitry Andric
toString() const728dbe13110SDimitry Andric const char *ConversionSpecifier::toString() const {
729dbe13110SDimitry Andric switch (kind) {
730e3b55780SDimitry Andric case bArg: return "b";
731e3b55780SDimitry Andric case BArg: return "B";
732dbe13110SDimitry Andric case dArg: return "d";
73313cc256eSDimitry Andric case DArg: return "D";
734dbe13110SDimitry Andric case iArg: return "i";
735dbe13110SDimitry Andric case oArg: return "o";
73613cc256eSDimitry Andric case OArg: return "O";
737dbe13110SDimitry Andric case uArg: return "u";
73813cc256eSDimitry Andric case UArg: return "U";
739dbe13110SDimitry Andric case xArg: return "x";
740dbe13110SDimitry Andric case XArg: return "X";
741dbe13110SDimitry Andric case fArg: return "f";
742dbe13110SDimitry Andric case FArg: return "F";
743dbe13110SDimitry Andric case eArg: return "e";
744dbe13110SDimitry Andric case EArg: return "E";
745dbe13110SDimitry Andric case gArg: return "g";
746dbe13110SDimitry Andric case GArg: return "G";
747dbe13110SDimitry Andric case aArg: return "a";
748dbe13110SDimitry Andric case AArg: return "A";
749dbe13110SDimitry Andric case cArg: return "c";
750dbe13110SDimitry Andric case sArg: return "s";
751dbe13110SDimitry Andric case pArg: return "p";
752bab175ecSDimitry Andric case PArg:
753bab175ecSDimitry Andric return "P";
754dbe13110SDimitry Andric case nArg: return "n";
755dbe13110SDimitry Andric case PercentArg: return "%";
756dbe13110SDimitry Andric case ScanListArg: return "[";
7579f4dbff6SDimitry Andric case InvalidSpecifier: return nullptr;
758dbe13110SDimitry Andric
759bfef3995SDimitry Andric // POSIX unicode extensions.
760dbe13110SDimitry Andric case CArg: return "C";
761dbe13110SDimitry Andric case SArg: return "S";
762dbe13110SDimitry Andric
763dbe13110SDimitry Andric // Objective-C specific specifiers.
764dbe13110SDimitry Andric case ObjCObjArg: return "@";
765dbe13110SDimitry Andric
7665e20cdd8SDimitry Andric // FreeBSD kernel specific specifiers.
7675e20cdd8SDimitry Andric case FreeBSDbArg: return "b";
7685e20cdd8SDimitry Andric case FreeBSDDArg: return "D";
7695e20cdd8SDimitry Andric case FreeBSDrArg: return "r";
7705e20cdd8SDimitry Andric case FreeBSDyArg: return "y";
7715e20cdd8SDimitry Andric
772dbe13110SDimitry Andric // GlibC specific specifiers.
773dbe13110SDimitry Andric case PrintErrno: return "m";
77406d4ba38SDimitry Andric
77506d4ba38SDimitry Andric // MS specific specifiers.
77606d4ba38SDimitry Andric case ZArg: return "Z";
777ac9a064cSDimitry Andric
778ac9a064cSDimitry Andric // ISO/IEC TR 18037 (fixed-point) specific specifiers.
779ac9a064cSDimitry Andric case rArg:
780ac9a064cSDimitry Andric return "r";
781ac9a064cSDimitry Andric case RArg:
782ac9a064cSDimitry Andric return "R";
783ac9a064cSDimitry Andric case kArg:
784ac9a064cSDimitry Andric return "k";
785ac9a064cSDimitry Andric case KArg:
786ac9a064cSDimitry Andric return "K";
787dbe13110SDimitry Andric }
7889f4dbff6SDimitry Andric return nullptr;
789dbe13110SDimitry Andric }
790dbe13110SDimitry Andric
791e3b55780SDimitry Andric std::optional<ConversionSpecifier>
getStandardSpecifier() const79213cc256eSDimitry Andric ConversionSpecifier::getStandardSpecifier() const {
79313cc256eSDimitry Andric ConversionSpecifier::Kind NewKind;
79413cc256eSDimitry Andric
79513cc256eSDimitry Andric switch (getKind()) {
79613cc256eSDimitry Andric default:
797e3b55780SDimitry Andric return std::nullopt;
79813cc256eSDimitry Andric case DArg:
79913cc256eSDimitry Andric NewKind = dArg;
80013cc256eSDimitry Andric break;
80113cc256eSDimitry Andric case UArg:
80213cc256eSDimitry Andric NewKind = uArg;
80313cc256eSDimitry Andric break;
80413cc256eSDimitry Andric case OArg:
80513cc256eSDimitry Andric NewKind = oArg;
80613cc256eSDimitry Andric break;
80713cc256eSDimitry Andric }
80813cc256eSDimitry Andric
80913cc256eSDimitry Andric ConversionSpecifier FixedCS(*this);
81013cc256eSDimitry Andric FixedCS.setKind(NewKind);
81113cc256eSDimitry Andric return FixedCS;
81213cc256eSDimitry Andric }
81313cc256eSDimitry Andric
814dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
8153d1dcd9bSDimitry Andric // Methods on OptionalAmount.
8163d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
8173d1dcd9bSDimitry Andric
toString(raw_ostream & os) const81836981b17SDimitry Andric void OptionalAmount::toString(raw_ostream &os) const {
8193d1dcd9bSDimitry Andric switch (hs) {
8203d1dcd9bSDimitry Andric case Invalid:
8213d1dcd9bSDimitry Andric case NotSpecified:
8223d1dcd9bSDimitry Andric return;
8233d1dcd9bSDimitry Andric case Arg:
8243d1dcd9bSDimitry Andric if (UsesDotPrefix)
8253d1dcd9bSDimitry Andric os << ".";
8263d1dcd9bSDimitry Andric if (usesPositionalArg())
8273d1dcd9bSDimitry Andric os << "*" << getPositionalArgIndex() << "$";
8283d1dcd9bSDimitry Andric else
8293d1dcd9bSDimitry Andric os << "*";
8303d1dcd9bSDimitry Andric break;
8313d1dcd9bSDimitry Andric case Constant:
8323d1dcd9bSDimitry Andric if (UsesDotPrefix)
8333d1dcd9bSDimitry Andric os << ".";
8343d1dcd9bSDimitry Andric os << amt;
8353d1dcd9bSDimitry Andric break;
8363d1dcd9bSDimitry Andric }
8373d1dcd9bSDimitry Andric }
8383d1dcd9bSDimitry Andric
hasValidLengthModifier(const TargetInfo & Target,const LangOptions & LO) const83922989816SDimitry Andric bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
84022989816SDimitry Andric const LangOptions &LO) const {
8413d1dcd9bSDimitry Andric switch (LM.getKind()) {
8423d1dcd9bSDimitry Andric case LengthModifier::None:
8433d1dcd9bSDimitry Andric return true;
8443d1dcd9bSDimitry Andric
8453d1dcd9bSDimitry Andric // Handle most integer flags
8463d1dcd9bSDimitry Andric case LengthModifier::AsShort:
84722989816SDimitry Andric // Length modifier only applies to FP vectors.
84822989816SDimitry Andric if (LO.OpenCL && CS.isDoubleArg())
84922989816SDimitry Andric return !VectorNumElts.isInvalid();
85022989816SDimitry Andric
851ac9a064cSDimitry Andric if (CS.isFixedPointArg())
852ac9a064cSDimitry Andric return true;
853ac9a064cSDimitry Andric
85406d4ba38SDimitry Andric if (Target.getTriple().isOSMSVCRT()) {
85506d4ba38SDimitry Andric switch (CS.getKind()) {
85606d4ba38SDimitry Andric case ConversionSpecifier::cArg:
85706d4ba38SDimitry Andric case ConversionSpecifier::CArg:
85806d4ba38SDimitry Andric case ConversionSpecifier::sArg:
85906d4ba38SDimitry Andric case ConversionSpecifier::SArg:
86006d4ba38SDimitry Andric case ConversionSpecifier::ZArg:
86106d4ba38SDimitry Andric return true;
86206d4ba38SDimitry Andric default:
86306d4ba38SDimitry Andric break;
86406d4ba38SDimitry Andric }
86506d4ba38SDimitry Andric }
866e3b55780SDimitry Andric [[fallthrough]];
86706d4ba38SDimitry Andric case LengthModifier::AsChar:
8683d1dcd9bSDimitry Andric case LengthModifier::AsLongLong:
869dbe13110SDimitry Andric case LengthModifier::AsQuad:
8703d1dcd9bSDimitry Andric case LengthModifier::AsIntMax:
8713d1dcd9bSDimitry Andric case LengthModifier::AsSizeT:
8723d1dcd9bSDimitry Andric case LengthModifier::AsPtrDiff:
8733d1dcd9bSDimitry Andric switch (CS.getKind()) {
874e3b55780SDimitry Andric case ConversionSpecifier::bArg:
875e3b55780SDimitry Andric case ConversionSpecifier::BArg:
8763d1dcd9bSDimitry Andric case ConversionSpecifier::dArg:
87713cc256eSDimitry Andric case ConversionSpecifier::DArg:
8783d1dcd9bSDimitry Andric case ConversionSpecifier::iArg:
8793d1dcd9bSDimitry Andric case ConversionSpecifier::oArg:
88013cc256eSDimitry Andric case ConversionSpecifier::OArg:
8813d1dcd9bSDimitry Andric case ConversionSpecifier::uArg:
88213cc256eSDimitry Andric case ConversionSpecifier::UArg:
8833d1dcd9bSDimitry Andric case ConversionSpecifier::xArg:
8843d1dcd9bSDimitry Andric case ConversionSpecifier::XArg:
8853d1dcd9bSDimitry Andric case ConversionSpecifier::nArg:
8863d1dcd9bSDimitry Andric return true;
8875e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDrArg:
8885e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDyArg:
889145449b1SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
8903d1dcd9bSDimitry Andric default:
8913d1dcd9bSDimitry Andric return false;
8923d1dcd9bSDimitry Andric }
8933d1dcd9bSDimitry Andric
89422989816SDimitry Andric case LengthModifier::AsShortLong:
89522989816SDimitry Andric return LO.OpenCL && !VectorNumElts.isInvalid();
89622989816SDimitry Andric
8973d1dcd9bSDimitry Andric // Handle 'l' flag
89806d4ba38SDimitry Andric case LengthModifier::AsLong: // or AsWideChar
89922989816SDimitry Andric if (CS.isDoubleArg()) {
90022989816SDimitry Andric // Invalid for OpenCL FP scalars.
90122989816SDimitry Andric if (LO.OpenCL && VectorNumElts.isInvalid())
90222989816SDimitry Andric return false;
90322989816SDimitry Andric return true;
90422989816SDimitry Andric }
90522989816SDimitry Andric
906ac9a064cSDimitry Andric if (CS.isFixedPointArg())
907ac9a064cSDimitry Andric return true;
908ac9a064cSDimitry Andric
9093d1dcd9bSDimitry Andric switch (CS.getKind()) {
9107fa27ce4SDimitry Andric case ConversionSpecifier::bArg:
9117fa27ce4SDimitry Andric case ConversionSpecifier::BArg:
9123d1dcd9bSDimitry Andric case ConversionSpecifier::dArg:
91313cc256eSDimitry Andric case ConversionSpecifier::DArg:
9143d1dcd9bSDimitry Andric case ConversionSpecifier::iArg:
9153d1dcd9bSDimitry Andric case ConversionSpecifier::oArg:
91613cc256eSDimitry Andric case ConversionSpecifier::OArg:
9173d1dcd9bSDimitry Andric case ConversionSpecifier::uArg:
91813cc256eSDimitry Andric case ConversionSpecifier::UArg:
9193d1dcd9bSDimitry Andric case ConversionSpecifier::xArg:
9203d1dcd9bSDimitry Andric case ConversionSpecifier::XArg:
9213d1dcd9bSDimitry Andric case ConversionSpecifier::nArg:
9223d1dcd9bSDimitry Andric case ConversionSpecifier::cArg:
9233d1dcd9bSDimitry Andric case ConversionSpecifier::sArg:
924dbe13110SDimitry Andric case ConversionSpecifier::ScanListArg:
92506d4ba38SDimitry Andric case ConversionSpecifier::ZArg:
9263d1dcd9bSDimitry Andric return true;
9275e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDrArg:
9285e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDyArg:
929145449b1SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
9303d1dcd9bSDimitry Andric default:
9313d1dcd9bSDimitry Andric return false;
9323d1dcd9bSDimitry Andric }
9333d1dcd9bSDimitry Andric
9343d1dcd9bSDimitry Andric case LengthModifier::AsLongDouble:
9353d1dcd9bSDimitry Andric switch (CS.getKind()) {
9363d1dcd9bSDimitry Andric case ConversionSpecifier::aArg:
9373d1dcd9bSDimitry Andric case ConversionSpecifier::AArg:
9383d1dcd9bSDimitry Andric case ConversionSpecifier::fArg:
9393d1dcd9bSDimitry Andric case ConversionSpecifier::FArg:
9403d1dcd9bSDimitry Andric case ConversionSpecifier::eArg:
9413d1dcd9bSDimitry Andric case ConversionSpecifier::EArg:
9423d1dcd9bSDimitry Andric case ConversionSpecifier::gArg:
9433d1dcd9bSDimitry Andric case ConversionSpecifier::GArg:
9443d1dcd9bSDimitry Andric return true;
94513cc256eSDimitry Andric // GNU libc extension.
946dbe13110SDimitry Andric case ConversionSpecifier::dArg:
947dbe13110SDimitry Andric case ConversionSpecifier::iArg:
948dbe13110SDimitry Andric case ConversionSpecifier::oArg:
949dbe13110SDimitry Andric case ConversionSpecifier::uArg:
950dbe13110SDimitry Andric case ConversionSpecifier::xArg:
951dbe13110SDimitry Andric case ConversionSpecifier::XArg:
95213cc256eSDimitry Andric return !Target.getTriple().isOSDarwin() &&
95313cc256eSDimitry Andric !Target.getTriple().isOSWindows();
954dbe13110SDimitry Andric default:
955dbe13110SDimitry Andric return false;
956dbe13110SDimitry Andric }
957dbe13110SDimitry Andric
958dbe13110SDimitry Andric case LengthModifier::AsAllocate:
959dbe13110SDimitry Andric switch (CS.getKind()) {
960dbe13110SDimitry Andric case ConversionSpecifier::sArg:
961dbe13110SDimitry Andric case ConversionSpecifier::SArg:
962dbe13110SDimitry Andric case ConversionSpecifier::ScanListArg:
963dbe13110SDimitry Andric return true;
964dbe13110SDimitry Andric default:
965dbe13110SDimitry Andric return false;
966dbe13110SDimitry Andric }
967dbe13110SDimitry Andric
968dbe13110SDimitry Andric case LengthModifier::AsMAllocate:
969dbe13110SDimitry Andric switch (CS.getKind()) {
970dbe13110SDimitry Andric case ConversionSpecifier::cArg:
971dbe13110SDimitry Andric case ConversionSpecifier::CArg:
972dbe13110SDimitry Andric case ConversionSpecifier::sArg:
973dbe13110SDimitry Andric case ConversionSpecifier::SArg:
974dbe13110SDimitry Andric case ConversionSpecifier::ScanListArg:
975dbe13110SDimitry Andric return true;
9763d1dcd9bSDimitry Andric default:
9773d1dcd9bSDimitry Andric return false;
9783d1dcd9bSDimitry Andric }
979bfef3995SDimitry Andric case LengthModifier::AsInt32:
980bfef3995SDimitry Andric case LengthModifier::AsInt3264:
981bfef3995SDimitry Andric case LengthModifier::AsInt64:
982bfef3995SDimitry Andric switch (CS.getKind()) {
983bfef3995SDimitry Andric case ConversionSpecifier::dArg:
984bfef3995SDimitry Andric case ConversionSpecifier::iArg:
985bfef3995SDimitry Andric case ConversionSpecifier::oArg:
986bfef3995SDimitry Andric case ConversionSpecifier::uArg:
987bfef3995SDimitry Andric case ConversionSpecifier::xArg:
988bfef3995SDimitry Andric case ConversionSpecifier::XArg:
989bfef3995SDimitry Andric return Target.getTriple().isOSMSVCRT();
990bfef3995SDimitry Andric default:
991bfef3995SDimitry Andric return false;
992bfef3995SDimitry Andric }
99306d4ba38SDimitry Andric case LengthModifier::AsWide:
99406d4ba38SDimitry Andric switch (CS.getKind()) {
99506d4ba38SDimitry Andric case ConversionSpecifier::cArg:
99606d4ba38SDimitry Andric case ConversionSpecifier::CArg:
99706d4ba38SDimitry Andric case ConversionSpecifier::sArg:
99806d4ba38SDimitry Andric case ConversionSpecifier::SArg:
99906d4ba38SDimitry Andric case ConversionSpecifier::ZArg:
100006d4ba38SDimitry Andric return Target.getTriple().isOSMSVCRT();
100106d4ba38SDimitry Andric default:
100206d4ba38SDimitry Andric return false;
100306d4ba38SDimitry Andric }
10043d1dcd9bSDimitry Andric }
1005dbe13110SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!");
10063d1dcd9bSDimitry Andric }
10073d1dcd9bSDimitry Andric
hasStandardLengthModifier() const1008dbe13110SDimitry Andric bool FormatSpecifier::hasStandardLengthModifier() const {
1009dbe13110SDimitry Andric switch (LM.getKind()) {
1010dbe13110SDimitry Andric case LengthModifier::None:
1011dbe13110SDimitry Andric case LengthModifier::AsChar:
1012dbe13110SDimitry Andric case LengthModifier::AsShort:
1013dbe13110SDimitry Andric case LengthModifier::AsLong:
1014dbe13110SDimitry Andric case LengthModifier::AsLongLong:
1015dbe13110SDimitry Andric case LengthModifier::AsIntMax:
1016dbe13110SDimitry Andric case LengthModifier::AsSizeT:
1017dbe13110SDimitry Andric case LengthModifier::AsPtrDiff:
1018dbe13110SDimitry Andric case LengthModifier::AsLongDouble:
1019dbe13110SDimitry Andric return true;
1020dbe13110SDimitry Andric case LengthModifier::AsAllocate:
1021dbe13110SDimitry Andric case LengthModifier::AsMAllocate:
1022dbe13110SDimitry Andric case LengthModifier::AsQuad:
1023bfef3995SDimitry Andric case LengthModifier::AsInt32:
1024bfef3995SDimitry Andric case LengthModifier::AsInt3264:
1025bfef3995SDimitry Andric case LengthModifier::AsInt64:
102606d4ba38SDimitry Andric case LengthModifier::AsWide:
102722989816SDimitry Andric case LengthModifier::AsShortLong: // ???
1028dbe13110SDimitry Andric return false;
1029dbe13110SDimitry Andric }
1030dbe13110SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!");
1031dbe13110SDimitry Andric }
10323d1dcd9bSDimitry Andric
hasStandardConversionSpecifier(const LangOptions & LangOpt) const10335e20cdd8SDimitry Andric bool FormatSpecifier::hasStandardConversionSpecifier(
10345e20cdd8SDimitry Andric const LangOptions &LangOpt) const {
1035dbe13110SDimitry Andric switch (CS.getKind()) {
1036e3b55780SDimitry Andric case ConversionSpecifier::bArg:
1037e3b55780SDimitry Andric case ConversionSpecifier::BArg:
1038dbe13110SDimitry Andric case ConversionSpecifier::cArg:
1039dbe13110SDimitry Andric case ConversionSpecifier::dArg:
1040dbe13110SDimitry Andric case ConversionSpecifier::iArg:
1041dbe13110SDimitry Andric case ConversionSpecifier::oArg:
1042dbe13110SDimitry Andric case ConversionSpecifier::uArg:
1043dbe13110SDimitry Andric case ConversionSpecifier::xArg:
1044dbe13110SDimitry Andric case ConversionSpecifier::XArg:
1045dbe13110SDimitry Andric case ConversionSpecifier::fArg:
1046dbe13110SDimitry Andric case ConversionSpecifier::FArg:
1047dbe13110SDimitry Andric case ConversionSpecifier::eArg:
1048dbe13110SDimitry Andric case ConversionSpecifier::EArg:
1049dbe13110SDimitry Andric case ConversionSpecifier::gArg:
1050dbe13110SDimitry Andric case ConversionSpecifier::GArg:
1051dbe13110SDimitry Andric case ConversionSpecifier::aArg:
1052dbe13110SDimitry Andric case ConversionSpecifier::AArg:
1053dbe13110SDimitry Andric case ConversionSpecifier::sArg:
1054dbe13110SDimitry Andric case ConversionSpecifier::pArg:
1055dbe13110SDimitry Andric case ConversionSpecifier::nArg:
1056dbe13110SDimitry Andric case ConversionSpecifier::ObjCObjArg:
1057dbe13110SDimitry Andric case ConversionSpecifier::ScanListArg:
1058dbe13110SDimitry Andric case ConversionSpecifier::PercentArg:
1059bab175ecSDimitry Andric case ConversionSpecifier::PArg:
1060dbe13110SDimitry Andric return true;
1061dbe13110SDimitry Andric case ConversionSpecifier::CArg:
1062dbe13110SDimitry Andric case ConversionSpecifier::SArg:
1063676fbe81SDimitry Andric return LangOpt.ObjC;
1064dbe13110SDimitry Andric case ConversionSpecifier::InvalidSpecifier:
10655e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDbArg:
10665e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDDArg:
10675e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDrArg:
10685e20cdd8SDimitry Andric case ConversionSpecifier::FreeBSDyArg:
1069dbe13110SDimitry Andric case ConversionSpecifier::PrintErrno:
107013cc256eSDimitry Andric case ConversionSpecifier::DArg:
107113cc256eSDimitry Andric case ConversionSpecifier::OArg:
107213cc256eSDimitry Andric case ConversionSpecifier::UArg:
107306d4ba38SDimitry Andric case ConversionSpecifier::ZArg:
1074dbe13110SDimitry Andric return false;
1075ac9a064cSDimitry Andric case ConversionSpecifier::rArg:
1076ac9a064cSDimitry Andric case ConversionSpecifier::RArg:
1077ac9a064cSDimitry Andric case ConversionSpecifier::kArg:
1078ac9a064cSDimitry Andric case ConversionSpecifier::KArg:
1079ac9a064cSDimitry Andric return LangOpt.FixedPoint;
1080dbe13110SDimitry Andric }
1081dbe13110SDimitry Andric llvm_unreachable("Invalid ConversionSpecifier Kind!");
1082dbe13110SDimitry Andric }
1083dbe13110SDimitry Andric
hasStandardLengthConversionCombination() const1084dbe13110SDimitry Andric bool FormatSpecifier::hasStandardLengthConversionCombination() const {
1085dbe13110SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble) {
1086dbe13110SDimitry Andric switch(CS.getKind()) {
1087dbe13110SDimitry Andric case ConversionSpecifier::dArg:
1088dbe13110SDimitry Andric case ConversionSpecifier::iArg:
1089dbe13110SDimitry Andric case ConversionSpecifier::oArg:
1090dbe13110SDimitry Andric case ConversionSpecifier::uArg:
1091dbe13110SDimitry Andric case ConversionSpecifier::xArg:
1092dbe13110SDimitry Andric case ConversionSpecifier::XArg:
1093dbe13110SDimitry Andric return false;
1094dbe13110SDimitry Andric default:
1095dbe13110SDimitry Andric return true;
1096dbe13110SDimitry Andric }
1097dbe13110SDimitry Andric }
1098dbe13110SDimitry Andric return true;
1099dbe13110SDimitry Andric }
110056d91b49SDimitry Andric
1101e3b55780SDimitry Andric std::optional<LengthModifier>
getCorrectedLengthModifier() const1102e3b55780SDimitry Andric FormatSpecifier::getCorrectedLengthModifier() const {
110313cc256eSDimitry Andric if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
110413cc256eSDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble ||
110513cc256eSDimitry Andric LM.getKind() == LengthModifier::AsQuad) {
110613cc256eSDimitry Andric LengthModifier FixedLM(LM);
110713cc256eSDimitry Andric FixedLM.setKind(LengthModifier::AsLongLong);
110813cc256eSDimitry Andric return FixedLM;
110913cc256eSDimitry Andric }
111013cc256eSDimitry Andric }
111113cc256eSDimitry Andric
1112e3b55780SDimitry Andric return std::nullopt;
111313cc256eSDimitry Andric }
111413cc256eSDimitry Andric
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)111556d91b49SDimitry Andric bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
111656d91b49SDimitry Andric LengthModifier &LM) {
1117e3b55780SDimitry Andric for (/**/; const auto *TT = QT->getAs<TypedefType>();
1118e3b55780SDimitry Andric QT = TT->getDecl()->getUnderlyingType()) {
1119e3b55780SDimitry Andric const TypedefNameDecl *Typedef = TT->getDecl();
112056d91b49SDimitry Andric const IdentifierInfo *Identifier = Typedef->getIdentifier();
112156d91b49SDimitry Andric if (Identifier->getName() == "size_t") {
112256d91b49SDimitry Andric LM.setKind(LengthModifier::AsSizeT);
112356d91b49SDimitry Andric return true;
112456d91b49SDimitry Andric } else if (Identifier->getName() == "ssize_t") {
112556d91b49SDimitry Andric // Not C99, but common in Unix.
112656d91b49SDimitry Andric LM.setKind(LengthModifier::AsSizeT);
112756d91b49SDimitry Andric return true;
112856d91b49SDimitry Andric } else if (Identifier->getName() == "intmax_t") {
112956d91b49SDimitry Andric LM.setKind(LengthModifier::AsIntMax);
113056d91b49SDimitry Andric return true;
113156d91b49SDimitry Andric } else if (Identifier->getName() == "uintmax_t") {
113256d91b49SDimitry Andric LM.setKind(LengthModifier::AsIntMax);
113356d91b49SDimitry Andric return true;
113456d91b49SDimitry Andric } else if (Identifier->getName() == "ptrdiff_t") {
113556d91b49SDimitry Andric LM.setKind(LengthModifier::AsPtrDiff);
113656d91b49SDimitry Andric return true;
113756d91b49SDimitry Andric }
113856d91b49SDimitry Andric }
113956d91b49SDimitry Andric return false;
114056d91b49SDimitry Andric }
1141