1314fbfa1STim Northover // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
2314fbfa1STim Northover //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6314fbfa1STim Northover //
7314fbfa1STim Northover //===----------------------------------------------------------------------===//
8314fbfa1STim Northover //
9314fbfa1STim Northover // Shared details for processing format strings of printf and scanf
10314fbfa1STim Northover // (and friends).
11314fbfa1STim Northover //
12314fbfa1STim Northover //===----------------------------------------------------------------------===//
13314fbfa1STim Northover
14314fbfa1STim Northover #include "FormatStringParsing.h"
15314fbfa1STim Northover #include "clang/Basic/LangOptions.h"
16314fbfa1STim Northover #include "clang/Basic/TargetInfo.h"
17314fbfa1STim Northover #include "llvm/Support/ConvertUTF.h"
18314fbfa1STim Northover
19314fbfa1STim Northover using clang::analyze_format_string::ArgType;
20314fbfa1STim Northover using clang::analyze_format_string::FormatStringHandler;
21314fbfa1STim Northover using clang::analyze_format_string::FormatSpecifier;
22314fbfa1STim Northover using clang::analyze_format_string::LengthModifier;
23314fbfa1STim Northover using clang::analyze_format_string::OptionalAmount;
24314fbfa1STim Northover using clang::analyze_format_string::ConversionSpecifier;
25314fbfa1STim Northover using namespace clang;
26314fbfa1STim Northover
27314fbfa1STim Northover // Key function to FormatStringHandler.
~FormatStringHandler()28314fbfa1STim Northover FormatStringHandler::~FormatStringHandler() {}
29314fbfa1STim Northover
30314fbfa1STim Northover //===----------------------------------------------------------------------===//
31314fbfa1STim Northover // Functions for parsing format strings components in both printf and
32314fbfa1STim Northover // scanf format strings.
33314fbfa1STim Northover //===----------------------------------------------------------------------===//
34314fbfa1STim Northover
35314fbfa1STim Northover OptionalAmount
ParseAmount(const char * & Beg,const char * E)36314fbfa1STim Northover clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
37314fbfa1STim Northover const char *I = Beg;
38314fbfa1STim Northover UpdateOnReturn <const char*> UpdateBeg(Beg, I);
39314fbfa1STim Northover
40314fbfa1STim Northover unsigned accumulator = 0;
41314fbfa1STim Northover bool hasDigits = false;
42314fbfa1STim Northover
43314fbfa1STim Northover for ( ; I != E; ++I) {
44314fbfa1STim Northover char c = *I;
45314fbfa1STim Northover if (c >= '0' && c <= '9') {
46314fbfa1STim Northover hasDigits = true;
47314fbfa1STim Northover accumulator = (accumulator * 10) + (c - '0');
48314fbfa1STim Northover continue;
49314fbfa1STim Northover }
50314fbfa1STim Northover
51314fbfa1STim Northover if (hasDigits)
52314fbfa1STim Northover return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
53314fbfa1STim Northover false);
54314fbfa1STim Northover
55314fbfa1STim Northover break;
56314fbfa1STim Northover }
57314fbfa1STim Northover
58314fbfa1STim Northover return OptionalAmount();
59314fbfa1STim Northover }
60314fbfa1STim Northover
61314fbfa1STim Northover OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)62314fbfa1STim Northover clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
63314fbfa1STim Northover const char *E,
64314fbfa1STim Northover unsigned &argIndex) {
65314fbfa1STim Northover if (*Beg == '*') {
66314fbfa1STim Northover ++Beg;
67314fbfa1STim Northover return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
68314fbfa1STim Northover }
69314fbfa1STim Northover
70314fbfa1STim Northover return ParseAmount(Beg, E);
71314fbfa1STim Northover }
72314fbfa1STim Northover
73314fbfa1STim Northover OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)74314fbfa1STim Northover clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
75314fbfa1STim Northover const char *Start,
76314fbfa1STim Northover const char *&Beg,
77314fbfa1STim Northover const char *E,
78314fbfa1STim Northover PositionContext p) {
79314fbfa1STim Northover if (*Beg == '*') {
80314fbfa1STim Northover const char *I = Beg + 1;
81314fbfa1STim Northover const OptionalAmount &Amt = ParseAmount(I, E);
82314fbfa1STim Northover
83314fbfa1STim Northover if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
84314fbfa1STim Northover H.HandleInvalidPosition(Beg, I - Beg, p);
85314fbfa1STim Northover return OptionalAmount(false);
86314fbfa1STim Northover }
87314fbfa1STim Northover
88314fbfa1STim Northover if (I == E) {
89314fbfa1STim Northover // No more characters left?
90314fbfa1STim Northover H.HandleIncompleteSpecifier(Start, E - Start);
91314fbfa1STim Northover return OptionalAmount(false);
92314fbfa1STim Northover }
93314fbfa1STim Northover
94314fbfa1STim Northover assert(Amt.getHowSpecified() == OptionalAmount::Constant);
95314fbfa1STim Northover
96314fbfa1STim Northover if (*I == '$') {
97314fbfa1STim Northover // Handle positional arguments
98314fbfa1STim Northover
99314fbfa1STim Northover // Special case: '*0$', since this is an easy mistake.
100314fbfa1STim Northover if (Amt.getConstantAmount() == 0) {
101314fbfa1STim Northover H.HandleZeroPosition(Beg, I - Beg + 1);
102314fbfa1STim Northover return OptionalAmount(false);
103314fbfa1STim Northover }
104314fbfa1STim Northover
105314fbfa1STim Northover const char *Tmp = Beg;
106314fbfa1STim Northover Beg = ++I;
107314fbfa1STim Northover
108314fbfa1STim Northover return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
109314fbfa1STim Northover Tmp, 0, true);
110314fbfa1STim Northover }
111314fbfa1STim Northover
112314fbfa1STim Northover H.HandleInvalidPosition(Beg, I - Beg, p);
113314fbfa1STim Northover return OptionalAmount(false);
114314fbfa1STim Northover }
115314fbfa1STim Northover
116314fbfa1STim Northover return ParseAmount(Beg, E);
117314fbfa1STim Northover }
118314fbfa1STim Northover
119314fbfa1STim Northover
120314fbfa1STim Northover bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)121314fbfa1STim Northover clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
122314fbfa1STim Northover FormatSpecifier &CS,
123314fbfa1STim Northover const char *Start,
124314fbfa1STim Northover const char *&Beg, const char *E,
125314fbfa1STim Northover unsigned *argIndex) {
126314fbfa1STim Northover // FIXME: Support negative field widths.
127314fbfa1STim Northover if (argIndex) {
128314fbfa1STim Northover CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
129314fbfa1STim Northover }
130314fbfa1STim Northover else {
131314fbfa1STim Northover const OptionalAmount Amt =
132314fbfa1STim Northover ParsePositionAmount(H, Start, Beg, E,
133314fbfa1STim Northover analyze_format_string::FieldWidthPos);
134314fbfa1STim Northover
135314fbfa1STim Northover if (Amt.isInvalid())
136314fbfa1STim Northover return true;
137314fbfa1STim Northover CS.setFieldWidth(Amt);
138314fbfa1STim Northover }
139314fbfa1STim Northover return false;
140314fbfa1STim Northover }
141314fbfa1STim Northover
142314fbfa1STim Northover bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)143314fbfa1STim Northover clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
144314fbfa1STim Northover FormatSpecifier &FS,
145314fbfa1STim Northover const char *Start,
146314fbfa1STim Northover const char *&Beg,
147314fbfa1STim Northover const char *E) {
148314fbfa1STim Northover const char *I = Beg;
149314fbfa1STim Northover
150314fbfa1STim Northover const OptionalAmount &Amt = ParseAmount(I, E);
151314fbfa1STim Northover
152314fbfa1STim Northover if (I == E) {
153314fbfa1STim Northover // No more characters left?
154314fbfa1STim Northover H.HandleIncompleteSpecifier(Start, E - Start);
155314fbfa1STim Northover return true;
156314fbfa1STim Northover }
157314fbfa1STim Northover
158314fbfa1STim Northover if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
159314fbfa1STim Northover // Warn that positional arguments are non-standard.
160314fbfa1STim Northover H.HandlePosition(Start, I - Start);
161314fbfa1STim Northover
162314fbfa1STim Northover // Special case: '%0$', since this is an easy mistake.
163314fbfa1STim Northover if (Amt.getConstantAmount() == 0) {
164314fbfa1STim Northover H.HandleZeroPosition(Start, I - Start);
165314fbfa1STim Northover return true;
166314fbfa1STim Northover }
167314fbfa1STim Northover
168314fbfa1STim Northover FS.setArgIndex(Amt.getConstantAmount() - 1);
169314fbfa1STim Northover FS.setUsesPositionalArg();
170314fbfa1STim Northover // Update the caller's pointer if we decided to consume
171314fbfa1STim Northover // these characters.
172314fbfa1STim Northover Beg = I;
173314fbfa1STim Northover return false;
174314fbfa1STim Northover }
175314fbfa1STim Northover
176314fbfa1STim Northover return false;
177314fbfa1STim Northover }
178314fbfa1STim Northover
179314fbfa1STim Northover bool
ParseVectorModifier(FormatStringHandler & H,FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO)1800ff50d49SMatt Arsenault clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
1810ff50d49SMatt Arsenault FormatSpecifier &FS,
1820ff50d49SMatt Arsenault const char *&I,
1830ff50d49SMatt Arsenault const char *E,
1840ff50d49SMatt Arsenault const LangOptions &LO) {
1850ff50d49SMatt Arsenault if (!LO.OpenCL)
1860ff50d49SMatt Arsenault return false;
1870ff50d49SMatt Arsenault
1880ff50d49SMatt Arsenault const char *Start = I;
1890ff50d49SMatt Arsenault if (*I == 'v') {
1900ff50d49SMatt Arsenault ++I;
1910ff50d49SMatt Arsenault
1920ff50d49SMatt Arsenault if (I == E) {
1930ff50d49SMatt Arsenault H.HandleIncompleteSpecifier(Start, E - Start);
1940ff50d49SMatt Arsenault return true;
1950ff50d49SMatt Arsenault }
1960ff50d49SMatt Arsenault
1970ff50d49SMatt Arsenault OptionalAmount NumElts = ParseAmount(I, E);
1980ff50d49SMatt Arsenault if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
1990ff50d49SMatt Arsenault H.HandleIncompleteSpecifier(Start, E - Start);
2000ff50d49SMatt Arsenault return true;
2010ff50d49SMatt Arsenault }
2020ff50d49SMatt Arsenault
2030ff50d49SMatt Arsenault FS.setVectorNumElts(NumElts);
2040ff50d49SMatt Arsenault }
2050ff50d49SMatt Arsenault
2060ff50d49SMatt Arsenault return false;
2070ff50d49SMatt Arsenault }
2080ff50d49SMatt Arsenault
2090ff50d49SMatt Arsenault bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)210314fbfa1STim Northover clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
211314fbfa1STim Northover const char *&I,
212314fbfa1STim Northover const char *E,
213314fbfa1STim Northover const LangOptions &LO,
214314fbfa1STim Northover bool IsScanf) {
215314fbfa1STim Northover LengthModifier::Kind lmKind = LengthModifier::None;
216314fbfa1STim Northover const char *lmPosition = I;
217314fbfa1STim Northover switch (*I) {
218314fbfa1STim Northover default:
219314fbfa1STim Northover return false;
220314fbfa1STim Northover case 'h':
221314fbfa1STim Northover ++I;
222314fbfa1STim Northover if (I != E && *I == 'h') {
223314fbfa1STim Northover ++I;
224314fbfa1STim Northover lmKind = LengthModifier::AsChar;
22558fc8082SMatt Arsenault } else if (I != E && *I == 'l' && LO.OpenCL) {
22658fc8082SMatt Arsenault ++I;
22758fc8082SMatt Arsenault lmKind = LengthModifier::AsShortLong;
228314fbfa1STim Northover } else {
229314fbfa1STim Northover lmKind = LengthModifier::AsShort;
230314fbfa1STim Northover }
231314fbfa1STim Northover break;
232314fbfa1STim Northover case 'l':
233314fbfa1STim Northover ++I;
234314fbfa1STim Northover if (I != E && *I == 'l') {
235314fbfa1STim Northover ++I;
236314fbfa1STim Northover lmKind = LengthModifier::AsLongLong;
237314fbfa1STim Northover } else {
238314fbfa1STim Northover lmKind = LengthModifier::AsLong;
239314fbfa1STim Northover }
240314fbfa1STim Northover break;
241314fbfa1STim Northover case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
242314fbfa1STim Northover case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
243314fbfa1STim Northover case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
244314fbfa1STim Northover case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
245314fbfa1STim Northover case 'q': lmKind = LengthModifier::AsQuad; ++I; break;
246314fbfa1STim Northover case 'a':
247314fbfa1STim Northover if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
248314fbfa1STim Northover // For scanf in C90, look at the next character to see if this should
249314fbfa1STim Northover // be parsed as the GNU extension 'a' length modifier. If not, this
250314fbfa1STim Northover // will be parsed as a conversion specifier.
251314fbfa1STim Northover ++I;
252314fbfa1STim Northover if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
253314fbfa1STim Northover lmKind = LengthModifier::AsAllocate;
254314fbfa1STim Northover break;
255314fbfa1STim Northover }
256314fbfa1STim Northover --I;
257314fbfa1STim Northover }
258314fbfa1STim Northover return false;
259314fbfa1STim Northover case 'm':
260314fbfa1STim Northover if (IsScanf) {
261314fbfa1STim Northover lmKind = LengthModifier::AsMAllocate;
262314fbfa1STim Northover ++I;
263314fbfa1STim Northover break;
264314fbfa1STim Northover }
265314fbfa1STim Northover return false;
266314fbfa1STim Northover // printf: AsInt64, AsInt32, AsInt3264
267314fbfa1STim Northover // scanf: AsInt64
268314fbfa1STim Northover case 'I':
269314fbfa1STim Northover if (I + 1 != E && I + 2 != E) {
270314fbfa1STim Northover if (I[1] == '6' && I[2] == '4') {
271314fbfa1STim Northover I += 3;
272314fbfa1STim Northover lmKind = LengthModifier::AsInt64;
273314fbfa1STim Northover break;
274314fbfa1STim Northover }
275314fbfa1STim Northover if (IsScanf)
276314fbfa1STim Northover return false;
277314fbfa1STim Northover
278314fbfa1STim Northover if (I[1] == '3' && I[2] == '2') {
279314fbfa1STim Northover I += 3;
280314fbfa1STim Northover lmKind = LengthModifier::AsInt32;
281314fbfa1STim Northover break;
282314fbfa1STim Northover }
283314fbfa1STim Northover }
284314fbfa1STim Northover ++I;
285314fbfa1STim Northover lmKind = LengthModifier::AsInt3264;
286314fbfa1STim Northover break;
287314fbfa1STim Northover case 'w':
288314fbfa1STim Northover lmKind = LengthModifier::AsWide; ++I; break;
289314fbfa1STim Northover }
290314fbfa1STim Northover LengthModifier lm(lmPosition, lmKind);
291314fbfa1STim Northover FS.setLengthModifier(lm);
292314fbfa1STim Northover return true;
293314fbfa1STim Northover }
294314fbfa1STim Northover
ParseUTF8InvalidSpecifier(const char * SpecifierBegin,const char * FmtStrEnd,unsigned & Len)295314fbfa1STim Northover bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
296314fbfa1STim Northover const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
297314fbfa1STim Northover if (SpecifierBegin + 1 >= FmtStrEnd)
298314fbfa1STim Northover return false;
299314fbfa1STim Northover
300314fbfa1STim Northover const llvm::UTF8 *SB =
301314fbfa1STim Northover reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
302314fbfa1STim Northover const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
303314fbfa1STim Northover const char FirstByte = *SB;
304314fbfa1STim Northover
305314fbfa1STim Northover // If the invalid specifier is a multibyte UTF-8 string, return the
306314fbfa1STim Northover // total length accordingly so that the conversion specifier can be
307314fbfa1STim Northover // properly updated to reflect a complete UTF-8 specifier.
308314fbfa1STim Northover unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
309314fbfa1STim Northover if (NumBytes == 1)
310314fbfa1STim Northover return false;
311314fbfa1STim Northover if (SB + NumBytes > SE)
312314fbfa1STim Northover return false;
313314fbfa1STim Northover
314314fbfa1STim Northover Len = NumBytes + 1;
315314fbfa1STim Northover return true;
316314fbfa1STim Northover }
317314fbfa1STim Northover
318314fbfa1STim Northover //===----------------------------------------------------------------------===//
319314fbfa1STim Northover // Methods on ArgType.
320314fbfa1STim Northover //===----------------------------------------------------------------------===//
321314fbfa1STim Northover
322314fbfa1STim Northover clang::analyze_format_string::ArgType::MatchKind
matchesType(ASTContext & C,QualType argTy) const323314fbfa1STim Northover ArgType::matchesType(ASTContext &C, QualType argTy) const {
32492edd74bSFélix Cloutier // When using the format attribute in C++, you can receive a function or an
32592edd74bSFélix Cloutier // array that will necessarily decay to a pointer when passed to the final
32692edd74bSFélix Cloutier // format consumer. Apply decay before type comparison.
32792edd74bSFélix Cloutier if (argTy->canDecayToPointerType())
32892edd74bSFélix Cloutier argTy = C.getDecayedType(argTy);
32992edd74bSFélix Cloutier
330314fbfa1STim Northover if (Ptr) {
331314fbfa1STim Northover // It has to be a pointer.
332314fbfa1STim Northover const PointerType *PT = argTy->getAs<PointerType>();
333314fbfa1STim Northover if (!PT)
334314fbfa1STim Northover return NoMatch;
335314fbfa1STim Northover
336314fbfa1STim Northover // We cannot write through a const qualified pointer.
337314fbfa1STim Northover if (PT->getPointeeType().isConstQualified())
338314fbfa1STim Northover return NoMatch;
339314fbfa1STim Northover
340314fbfa1STim Northover argTy = PT->getPointeeType();
341314fbfa1STim Northover }
342314fbfa1STim Northover
343314fbfa1STim Northover switch (K) {
344314fbfa1STim Northover case InvalidTy:
345314fbfa1STim Northover llvm_unreachable("ArgType must be valid");
346314fbfa1STim Northover
347314fbfa1STim Northover case UnknownTy:
348314fbfa1STim Northover return Match;
349314fbfa1STim Northover
350314fbfa1STim Northover case AnyCharTy: {
351314fbfa1STim Northover if (const EnumType *ETy = argTy->getAs<EnumType>()) {
352314fbfa1STim Northover // If the enum is incomplete we know nothing about the underlying type.
353314fbfa1STim Northover // Assume that it's 'int'.
354314fbfa1STim Northover if (!ETy->getDecl()->isComplete())
355314fbfa1STim Northover return NoMatch;
356314fbfa1STim Northover argTy = ETy->getDecl()->getIntegerType();
357314fbfa1STim Northover }
358314fbfa1STim Northover
359314fbfa1STim Northover if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
360314fbfa1STim Northover switch (BT->getKind()) {
361314fbfa1STim Northover default:
362314fbfa1STim Northover break;
363314fbfa1STim Northover case BuiltinType::Char_S:
364314fbfa1STim Northover case BuiltinType::SChar:
365314fbfa1STim Northover case BuiltinType::UChar:
366314fbfa1STim Northover case BuiltinType::Char_U:
3675741d19fSErik Pilkington case BuiltinType::Bool:
368314fbfa1STim Northover return Match;
369314fbfa1STim Northover }
370314fbfa1STim Northover return NoMatch;
371314fbfa1STim Northover }
372314fbfa1STim Northover
373314fbfa1STim Northover case SpecificTy: {
374314fbfa1STim Northover if (const EnumType *ETy = argTy->getAs<EnumType>()) {
375314fbfa1STim Northover // If the enum is incomplete we know nothing about the underlying type.
376314fbfa1STim Northover // Assume that it's 'int'.
377314fbfa1STim Northover if (!ETy->getDecl()->isComplete())
378314fbfa1STim Northover argTy = C.IntTy;
379314fbfa1STim Northover else
380314fbfa1STim Northover argTy = ETy->getDecl()->getIntegerType();
381314fbfa1STim Northover }
382314fbfa1STim Northover argTy = C.getCanonicalType(argTy).getUnqualifiedType();
383314fbfa1STim Northover
384314fbfa1STim Northover if (T == argTy)
385314fbfa1STim Northover return Match;
386314fbfa1STim Northover // Check for "compatible types".
387314fbfa1STim Northover if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
388314fbfa1STim Northover switch (BT->getKind()) {
389314fbfa1STim Northover default:
390314fbfa1STim Northover break;
391314fbfa1STim Northover case BuiltinType::Char_S:
392314fbfa1STim Northover case BuiltinType::SChar:
393314fbfa1STim Northover case BuiltinType::Char_U:
394314fbfa1STim Northover case BuiltinType::UChar:
3955741d19fSErik Pilkington case BuiltinType::Bool:
396cc01d642SNathan Huckleberry if (T == C.UnsignedShortTy || T == C.ShortTy)
397f7766b1eSErik Pilkington return NoMatchTypeConfusion;
398314fbfa1STim Northover return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
399314fbfa1STim Northover : NoMatch;
400314fbfa1STim Northover case BuiltinType::Short:
401314fbfa1STim Northover return T == C.UnsignedShortTy ? Match : NoMatch;
402314fbfa1STim Northover case BuiltinType::UShort:
403314fbfa1STim Northover return T == C.ShortTy ? Match : NoMatch;
404314fbfa1STim Northover case BuiltinType::Int:
405314fbfa1STim Northover return T == C.UnsignedIntTy ? Match : NoMatch;
406314fbfa1STim Northover case BuiltinType::UInt:
407314fbfa1STim Northover return T == C.IntTy ? Match : NoMatch;
408314fbfa1STim Northover case BuiltinType::Long:
409314fbfa1STim Northover return T == C.UnsignedLongTy ? Match : NoMatch;
410314fbfa1STim Northover case BuiltinType::ULong:
411314fbfa1STim Northover return T == C.LongTy ? Match : NoMatch;
412314fbfa1STim Northover case BuiltinType::LongLong:
413314fbfa1STim Northover return T == C.UnsignedLongLongTy ? Match : NoMatch;
414314fbfa1STim Northover case BuiltinType::ULongLong:
415314fbfa1STim Northover return T == C.LongLongTy ? Match : NoMatch;
416314fbfa1STim Northover }
417314fbfa1STim Northover return NoMatch;
418314fbfa1STim Northover }
419314fbfa1STim Northover
420314fbfa1STim Northover case CStrTy: {
421314fbfa1STim Northover const PointerType *PT = argTy->getAs<PointerType>();
422314fbfa1STim Northover if (!PT)
423314fbfa1STim Northover return NoMatch;
424314fbfa1STim Northover QualType pointeeTy = PT->getPointeeType();
425314fbfa1STim Northover if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
426314fbfa1STim Northover switch (BT->getKind()) {
427314fbfa1STim Northover case BuiltinType::Char_U:
428314fbfa1STim Northover case BuiltinType::UChar:
429314fbfa1STim Northover case BuiltinType::Char_S:
430314fbfa1STim Northover case BuiltinType::SChar:
431314fbfa1STim Northover return Match;
432314fbfa1STim Northover default:
433314fbfa1STim Northover break;
434314fbfa1STim Northover }
435314fbfa1STim Northover
436314fbfa1STim Northover return NoMatch;
437314fbfa1STim Northover }
438314fbfa1STim Northover
439314fbfa1STim Northover case WCStrTy: {
440314fbfa1STim Northover const PointerType *PT = argTy->getAs<PointerType>();
441314fbfa1STim Northover if (!PT)
442314fbfa1STim Northover return NoMatch;
443314fbfa1STim Northover QualType pointeeTy =
444314fbfa1STim Northover C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
445314fbfa1STim Northover return pointeeTy == C.getWideCharType() ? Match : NoMatch;
446314fbfa1STim Northover }
447314fbfa1STim Northover
448314fbfa1STim Northover case WIntTy: {
449314fbfa1STim Northover QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
450314fbfa1STim Northover
451314fbfa1STim Northover if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
452314fbfa1STim Northover return Match;
453314fbfa1STim Northover
454314fbfa1STim Northover QualType PromoArg = argTy->isPromotableIntegerType()
455314fbfa1STim Northover ? C.getPromotedIntegerType(argTy)
456314fbfa1STim Northover : argTy;
457314fbfa1STim Northover PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
458314fbfa1STim Northover
459314fbfa1STim Northover // If the promoted argument is the corresponding signed type of the
460314fbfa1STim Northover // wint_t type, then it should match.
461314fbfa1STim Northover if (PromoArg->hasSignedIntegerRepresentation() &&
462314fbfa1STim Northover C.getCorrespondingUnsignedType(PromoArg) == WInt)
463314fbfa1STim Northover return Match;
464314fbfa1STim Northover
465314fbfa1STim Northover return WInt == PromoArg ? Match : NoMatch;
466314fbfa1STim Northover }
467314fbfa1STim Northover
468314fbfa1STim Northover case CPointerTy:
469314fbfa1STim Northover if (argTy->isVoidPointerType()) {
470314fbfa1STim Northover return Match;
471314fbfa1STim Northover } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
472314fbfa1STim Northover argTy->isBlockPointerType() || argTy->isNullPtrType()) {
473314fbfa1STim Northover return NoMatchPedantic;
474314fbfa1STim Northover } else {
475314fbfa1STim Northover return NoMatch;
476314fbfa1STim Northover }
477314fbfa1STim Northover
478314fbfa1STim Northover case ObjCPointerTy: {
479314fbfa1STim Northover if (argTy->getAs<ObjCObjectPointerType>() ||
480314fbfa1STim Northover argTy->getAs<BlockPointerType>())
481314fbfa1STim Northover return Match;
482314fbfa1STim Northover
483314fbfa1STim Northover // Handle implicit toll-free bridging.
484314fbfa1STim Northover if (const PointerType *PT = argTy->getAs<PointerType>()) {
485314fbfa1STim Northover // Things such as CFTypeRef are really just opaque pointers
486314fbfa1STim Northover // to C structs representing CF types that can often be bridged
487314fbfa1STim Northover // to Objective-C objects. Since the compiler doesn't know which
488314fbfa1STim Northover // structs can be toll-free bridged, we just accept them all.
489314fbfa1STim Northover QualType pointee = PT->getPointeeType();
490314fbfa1STim Northover if (pointee->getAsStructureType() || pointee->isVoidType())
491314fbfa1STim Northover return Match;
492314fbfa1STim Northover }
493314fbfa1STim Northover return NoMatch;
494314fbfa1STim Northover }
495314fbfa1STim Northover }
496314fbfa1STim Northover
497314fbfa1STim Northover llvm_unreachable("Invalid ArgType Kind!");
498314fbfa1STim Northover }
499314fbfa1STim Northover
makeVectorType(ASTContext & C,unsigned NumElts) const5000ff50d49SMatt Arsenault ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
50158fc8082SMatt Arsenault // Check for valid vector element types.
50258fc8082SMatt Arsenault if (T.isNull())
5030ff50d49SMatt Arsenault return ArgType::Invalid();
5040ff50d49SMatt Arsenault
5050ff50d49SMatt Arsenault QualType Vec = C.getExtVectorType(T, NumElts);
5060ff50d49SMatt Arsenault return ArgType(Vec, Name);
5070ff50d49SMatt Arsenault }
5080ff50d49SMatt Arsenault
getRepresentativeType(ASTContext & C) const509314fbfa1STim Northover QualType ArgType::getRepresentativeType(ASTContext &C) const {
510314fbfa1STim Northover QualType Res;
511314fbfa1STim Northover switch (K) {
512314fbfa1STim Northover case InvalidTy:
513314fbfa1STim Northover llvm_unreachable("No representative type for Invalid ArgType");
514314fbfa1STim Northover case UnknownTy:
515314fbfa1STim Northover llvm_unreachable("No representative type for Unknown ArgType");
516314fbfa1STim Northover case AnyCharTy:
517314fbfa1STim Northover Res = C.CharTy;
518314fbfa1STim Northover break;
519314fbfa1STim Northover case SpecificTy:
520314fbfa1STim Northover Res = T;
521314fbfa1STim Northover break;
522314fbfa1STim Northover case CStrTy:
523314fbfa1STim Northover Res = C.getPointerType(C.CharTy);
524314fbfa1STim Northover break;
525314fbfa1STim Northover case WCStrTy:
526314fbfa1STim Northover Res = C.getPointerType(C.getWideCharType());
527314fbfa1STim Northover break;
528314fbfa1STim Northover case ObjCPointerTy:
529314fbfa1STim Northover Res = C.ObjCBuiltinIdTy;
530314fbfa1STim Northover break;
531314fbfa1STim Northover case CPointerTy:
532314fbfa1STim Northover Res = C.VoidPtrTy;
533314fbfa1STim Northover break;
534314fbfa1STim Northover case WIntTy: {
535314fbfa1STim Northover Res = C.getWIntType();
536314fbfa1STim Northover break;
537314fbfa1STim Northover }
538314fbfa1STim Northover }
539314fbfa1STim Northover
540314fbfa1STim Northover if (Ptr)
541314fbfa1STim Northover Res = C.getPointerType(Res);
542314fbfa1STim Northover return Res;
543314fbfa1STim Northover }
544314fbfa1STim Northover
getRepresentativeTypeName(ASTContext & C) const545314fbfa1STim Northover std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
5465fee6936SJessica Clarke std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
547314fbfa1STim Northover
548314fbfa1STim Northover std::string Alias;
549314fbfa1STim Northover if (Name) {
550314fbfa1STim Northover // Use a specific name for this type, e.g. "size_t".
551314fbfa1STim Northover Alias = Name;
552314fbfa1STim Northover if (Ptr) {
553314fbfa1STim Northover // If ArgType is actually a pointer to T, append an asterisk.
554314fbfa1STim Northover Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
555314fbfa1STim Northover }
556314fbfa1STim Northover // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
557314fbfa1STim Northover if (S == Alias)
558314fbfa1STim Northover Alias.clear();
559314fbfa1STim Northover }
560314fbfa1STim Northover
561314fbfa1STim Northover if (!Alias.empty())
562314fbfa1STim Northover return std::string("'") + Alias + "' (aka '" + S + "')";
563314fbfa1STim Northover return std::string("'") + S + "'";
564314fbfa1STim Northover }
565314fbfa1STim Northover
566314fbfa1STim Northover
567314fbfa1STim Northover //===----------------------------------------------------------------------===//
568314fbfa1STim Northover // Methods on OptionalAmount.
569314fbfa1STim Northover //===----------------------------------------------------------------------===//
570314fbfa1STim Northover
571314fbfa1STim Northover ArgType
getArgType(ASTContext & Ctx) const572314fbfa1STim Northover analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
573314fbfa1STim Northover return Ctx.IntTy;
574314fbfa1STim Northover }
575314fbfa1STim Northover
576314fbfa1STim Northover //===----------------------------------------------------------------------===//
577314fbfa1STim Northover // Methods on LengthModifier.
578314fbfa1STim Northover //===----------------------------------------------------------------------===//
579314fbfa1STim Northover
580314fbfa1STim Northover const char *
toString() const581314fbfa1STim Northover analyze_format_string::LengthModifier::toString() const {
582314fbfa1STim Northover switch (kind) {
583314fbfa1STim Northover case AsChar:
584314fbfa1STim Northover return "hh";
585314fbfa1STim Northover case AsShort:
586314fbfa1STim Northover return "h";
58758fc8082SMatt Arsenault case AsShortLong:
58858fc8082SMatt Arsenault return "hl";
589314fbfa1STim Northover case AsLong: // or AsWideChar
590314fbfa1STim Northover return "l";
591314fbfa1STim Northover case AsLongLong:
592314fbfa1STim Northover return "ll";
593314fbfa1STim Northover case AsQuad:
594314fbfa1STim Northover return "q";
595314fbfa1STim Northover case AsIntMax:
596314fbfa1STim Northover return "j";
597314fbfa1STim Northover case AsSizeT:
598314fbfa1STim Northover return "z";
599314fbfa1STim Northover case AsPtrDiff:
600314fbfa1STim Northover return "t";
601314fbfa1STim Northover case AsInt32:
602314fbfa1STim Northover return "I32";
603314fbfa1STim Northover case AsInt3264:
604314fbfa1STim Northover return "I";
605314fbfa1STim Northover case AsInt64:
606314fbfa1STim Northover return "I64";
607314fbfa1STim Northover case AsLongDouble:
608314fbfa1STim Northover return "L";
609314fbfa1STim Northover case AsAllocate:
610314fbfa1STim Northover return "a";
611314fbfa1STim Northover case AsMAllocate:
612314fbfa1STim Northover return "m";
613314fbfa1STim Northover case AsWide:
614314fbfa1STim Northover return "w";
615314fbfa1STim Northover case None:
616314fbfa1STim Northover return "";
617314fbfa1STim Northover }
618314fbfa1STim Northover return nullptr;
619314fbfa1STim Northover }
620314fbfa1STim Northover
621314fbfa1STim Northover //===----------------------------------------------------------------------===//
622314fbfa1STim Northover // Methods on ConversionSpecifier.
623314fbfa1STim Northover //===----------------------------------------------------------------------===//
624314fbfa1STim Northover
toString() const625314fbfa1STim Northover const char *ConversionSpecifier::toString() const {
626314fbfa1STim Northover switch (kind) {
627314fbfa1STim Northover case dArg: return "d";
628314fbfa1STim Northover case DArg: return "D";
629314fbfa1STim Northover case iArg: return "i";
630314fbfa1STim Northover case oArg: return "o";
631314fbfa1STim Northover case OArg: return "O";
632314fbfa1STim Northover case uArg: return "u";
633314fbfa1STim Northover case UArg: return "U";
634314fbfa1STim Northover case xArg: return "x";
635314fbfa1STim Northover case XArg: return "X";
636314fbfa1STim Northover case fArg: return "f";
637314fbfa1STim Northover case FArg: return "F";
638314fbfa1STim Northover case eArg: return "e";
639314fbfa1STim Northover case EArg: return "E";
640314fbfa1STim Northover case gArg: return "g";
641314fbfa1STim Northover case GArg: return "G";
642314fbfa1STim Northover case aArg: return "a";
643314fbfa1STim Northover case AArg: return "A";
644314fbfa1STim Northover case cArg: return "c";
645314fbfa1STim Northover case sArg: return "s";
646314fbfa1STim Northover case pArg: return "p";
647314fbfa1STim Northover case PArg:
648314fbfa1STim Northover return "P";
649314fbfa1STim Northover case nArg: return "n";
650314fbfa1STim Northover case PercentArg: return "%";
651314fbfa1STim Northover case ScanListArg: return "[";
652314fbfa1STim Northover case InvalidSpecifier: return nullptr;
653314fbfa1STim Northover
654314fbfa1STim Northover // POSIX unicode extensions.
655314fbfa1STim Northover case CArg: return "C";
656314fbfa1STim Northover case SArg: return "S";
657314fbfa1STim Northover
658314fbfa1STim Northover // Objective-C specific specifiers.
659314fbfa1STim Northover case ObjCObjArg: return "@";
660314fbfa1STim Northover
661314fbfa1STim Northover // FreeBSD kernel specific specifiers.
662314fbfa1STim Northover case FreeBSDbArg: return "b";
663314fbfa1STim Northover case FreeBSDDArg: return "D";
664314fbfa1STim Northover case FreeBSDrArg: return "r";
665314fbfa1STim Northover case FreeBSDyArg: return "y";
666314fbfa1STim Northover
667314fbfa1STim Northover // GlibC specific specifiers.
668314fbfa1STim Northover case PrintErrno: return "m";
669314fbfa1STim Northover
670314fbfa1STim Northover // MS specific specifiers.
671314fbfa1STim Northover case ZArg: return "Z";
672314fbfa1STim Northover }
673314fbfa1STim Northover return nullptr;
674314fbfa1STim Northover }
675314fbfa1STim Northover
676314fbfa1STim Northover Optional<ConversionSpecifier>
getStandardSpecifier() const677314fbfa1STim Northover ConversionSpecifier::getStandardSpecifier() const {
678314fbfa1STim Northover ConversionSpecifier::Kind NewKind;
679314fbfa1STim Northover
680314fbfa1STim Northover switch (getKind()) {
681314fbfa1STim Northover default:
682314fbfa1STim Northover return None;
683314fbfa1STim Northover case DArg:
684314fbfa1STim Northover NewKind = dArg;
685314fbfa1STim Northover break;
686314fbfa1STim Northover case UArg:
687314fbfa1STim Northover NewKind = uArg;
688314fbfa1STim Northover break;
689314fbfa1STim Northover case OArg:
690314fbfa1STim Northover NewKind = oArg;
691314fbfa1STim Northover break;
692314fbfa1STim Northover }
693314fbfa1STim Northover
694314fbfa1STim Northover ConversionSpecifier FixedCS(*this);
695314fbfa1STim Northover FixedCS.setKind(NewKind);
696314fbfa1STim Northover return FixedCS;
697314fbfa1STim Northover }
698314fbfa1STim Northover
699314fbfa1STim Northover //===----------------------------------------------------------------------===//
700314fbfa1STim Northover // Methods on OptionalAmount.
701314fbfa1STim Northover //===----------------------------------------------------------------------===//
702314fbfa1STim Northover
toString(raw_ostream & os) const703314fbfa1STim Northover void OptionalAmount::toString(raw_ostream &os) const {
704314fbfa1STim Northover switch (hs) {
705314fbfa1STim Northover case Invalid:
706314fbfa1STim Northover case NotSpecified:
707314fbfa1STim Northover return;
708314fbfa1STim Northover case Arg:
709314fbfa1STim Northover if (UsesDotPrefix)
710314fbfa1STim Northover os << ".";
711314fbfa1STim Northover if (usesPositionalArg())
712314fbfa1STim Northover os << "*" << getPositionalArgIndex() << "$";
713314fbfa1STim Northover else
714314fbfa1STim Northover os << "*";
715314fbfa1STim Northover break;
716314fbfa1STim Northover case Constant:
717314fbfa1STim Northover if (UsesDotPrefix)
718314fbfa1STim Northover os << ".";
719314fbfa1STim Northover os << amt;
720314fbfa1STim Northover break;
721314fbfa1STim Northover }
722314fbfa1STim Northover }
723314fbfa1STim Northover
hasValidLengthModifier(const TargetInfo & Target,const LangOptions & LO) const72458fc8082SMatt Arsenault bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
72558fc8082SMatt Arsenault const LangOptions &LO) const {
726314fbfa1STim Northover switch (LM.getKind()) {
727314fbfa1STim Northover case LengthModifier::None:
728314fbfa1STim Northover return true;
729314fbfa1STim Northover
730314fbfa1STim Northover // Handle most integer flags
731314fbfa1STim Northover case LengthModifier::AsShort:
73258fc8082SMatt Arsenault // Length modifier only applies to FP vectors.
73358fc8082SMatt Arsenault if (LO.OpenCL && CS.isDoubleArg())
73458fc8082SMatt Arsenault return !VectorNumElts.isInvalid();
73558fc8082SMatt Arsenault
736314fbfa1STim Northover if (Target.getTriple().isOSMSVCRT()) {
737314fbfa1STim Northover switch (CS.getKind()) {
738314fbfa1STim Northover case ConversionSpecifier::cArg:
739314fbfa1STim Northover case ConversionSpecifier::CArg:
740314fbfa1STim Northover case ConversionSpecifier::sArg:
741314fbfa1STim Northover case ConversionSpecifier::SArg:
742314fbfa1STim Northover case ConversionSpecifier::ZArg:
743314fbfa1STim Northover return true;
744314fbfa1STim Northover default:
745314fbfa1STim Northover break;
746314fbfa1STim Northover }
747314fbfa1STim Northover }
748314fbfa1STim Northover LLVM_FALLTHROUGH;
749314fbfa1STim Northover case LengthModifier::AsChar:
750314fbfa1STim Northover case LengthModifier::AsLongLong:
751314fbfa1STim Northover case LengthModifier::AsQuad:
752314fbfa1STim Northover case LengthModifier::AsIntMax:
753314fbfa1STim Northover case LengthModifier::AsSizeT:
754314fbfa1STim Northover case LengthModifier::AsPtrDiff:
755314fbfa1STim Northover switch (CS.getKind()) {
756314fbfa1STim Northover case ConversionSpecifier::dArg:
757314fbfa1STim Northover case ConversionSpecifier::DArg:
758314fbfa1STim Northover case ConversionSpecifier::iArg:
759314fbfa1STim Northover case ConversionSpecifier::oArg:
760314fbfa1STim Northover case ConversionSpecifier::OArg:
761314fbfa1STim Northover case ConversionSpecifier::uArg:
762314fbfa1STim Northover case ConversionSpecifier::UArg:
763314fbfa1STim Northover case ConversionSpecifier::xArg:
764314fbfa1STim Northover case ConversionSpecifier::XArg:
765314fbfa1STim Northover case ConversionSpecifier::nArg:
766314fbfa1STim Northover return true;
767314fbfa1STim Northover case ConversionSpecifier::FreeBSDrArg:
768314fbfa1STim Northover case ConversionSpecifier::FreeBSDyArg:
769b2c6251cSPaul Robinson return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
770314fbfa1STim Northover default:
771314fbfa1STim Northover return false;
772314fbfa1STim Northover }
773314fbfa1STim Northover
77458fc8082SMatt Arsenault case LengthModifier::AsShortLong:
77558fc8082SMatt Arsenault return LO.OpenCL && !VectorNumElts.isInvalid();
77658fc8082SMatt Arsenault
777314fbfa1STim Northover // Handle 'l' flag
778314fbfa1STim Northover case LengthModifier::AsLong: // or AsWideChar
77958fc8082SMatt Arsenault if (CS.isDoubleArg()) {
78058fc8082SMatt Arsenault // Invalid for OpenCL FP scalars.
78158fc8082SMatt Arsenault if (LO.OpenCL && VectorNumElts.isInvalid())
78258fc8082SMatt Arsenault return false;
78358fc8082SMatt Arsenault return true;
78458fc8082SMatt Arsenault }
78558fc8082SMatt Arsenault
786314fbfa1STim Northover switch (CS.getKind()) {
787314fbfa1STim Northover case ConversionSpecifier::dArg:
788314fbfa1STim Northover case ConversionSpecifier::DArg:
789314fbfa1STim Northover case ConversionSpecifier::iArg:
790314fbfa1STim Northover case ConversionSpecifier::oArg:
791314fbfa1STim Northover case ConversionSpecifier::OArg:
792314fbfa1STim Northover case ConversionSpecifier::uArg:
793314fbfa1STim Northover case ConversionSpecifier::UArg:
794314fbfa1STim Northover case ConversionSpecifier::xArg:
795314fbfa1STim Northover case ConversionSpecifier::XArg:
796314fbfa1STim Northover case ConversionSpecifier::nArg:
797314fbfa1STim Northover case ConversionSpecifier::cArg:
798314fbfa1STim Northover case ConversionSpecifier::sArg:
799314fbfa1STim Northover case ConversionSpecifier::ScanListArg:
800314fbfa1STim Northover case ConversionSpecifier::ZArg:
801314fbfa1STim Northover return true;
802314fbfa1STim Northover case ConversionSpecifier::FreeBSDrArg:
803314fbfa1STim Northover case ConversionSpecifier::FreeBSDyArg:
804b2c6251cSPaul Robinson return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
805314fbfa1STim Northover default:
806314fbfa1STim Northover return false;
807314fbfa1STim Northover }
808314fbfa1STim Northover
809314fbfa1STim Northover case LengthModifier::AsLongDouble:
810314fbfa1STim Northover switch (CS.getKind()) {
811314fbfa1STim Northover case ConversionSpecifier::aArg:
812314fbfa1STim Northover case ConversionSpecifier::AArg:
813314fbfa1STim Northover case ConversionSpecifier::fArg:
814314fbfa1STim Northover case ConversionSpecifier::FArg:
815314fbfa1STim Northover case ConversionSpecifier::eArg:
816314fbfa1STim Northover case ConversionSpecifier::EArg:
817314fbfa1STim Northover case ConversionSpecifier::gArg:
818314fbfa1STim Northover case ConversionSpecifier::GArg:
819314fbfa1STim Northover return true;
820314fbfa1STim Northover // GNU libc extension.
821314fbfa1STim Northover case ConversionSpecifier::dArg:
822314fbfa1STim Northover case ConversionSpecifier::iArg:
823314fbfa1STim Northover case ConversionSpecifier::oArg:
824314fbfa1STim Northover case ConversionSpecifier::uArg:
825314fbfa1STim Northover case ConversionSpecifier::xArg:
826314fbfa1STim Northover case ConversionSpecifier::XArg:
827314fbfa1STim Northover return !Target.getTriple().isOSDarwin() &&
828314fbfa1STim Northover !Target.getTriple().isOSWindows();
829314fbfa1STim Northover default:
830314fbfa1STim Northover return false;
831314fbfa1STim Northover }
832314fbfa1STim Northover
833314fbfa1STim Northover case LengthModifier::AsAllocate:
834314fbfa1STim Northover switch (CS.getKind()) {
835314fbfa1STim Northover case ConversionSpecifier::sArg:
836314fbfa1STim Northover case ConversionSpecifier::SArg:
837314fbfa1STim Northover case ConversionSpecifier::ScanListArg:
838314fbfa1STim Northover return true;
839314fbfa1STim Northover default:
840314fbfa1STim Northover return false;
841314fbfa1STim Northover }
842314fbfa1STim Northover
843314fbfa1STim Northover case LengthModifier::AsMAllocate:
844314fbfa1STim Northover switch (CS.getKind()) {
845314fbfa1STim Northover case ConversionSpecifier::cArg:
846314fbfa1STim Northover case ConversionSpecifier::CArg:
847314fbfa1STim Northover case ConversionSpecifier::sArg:
848314fbfa1STim Northover case ConversionSpecifier::SArg:
849314fbfa1STim Northover case ConversionSpecifier::ScanListArg:
850314fbfa1STim Northover return true;
851314fbfa1STim Northover default:
852314fbfa1STim Northover return false;
853314fbfa1STim Northover }
854314fbfa1STim Northover case LengthModifier::AsInt32:
855314fbfa1STim Northover case LengthModifier::AsInt3264:
856314fbfa1STim Northover case LengthModifier::AsInt64:
857314fbfa1STim Northover switch (CS.getKind()) {
858314fbfa1STim Northover case ConversionSpecifier::dArg:
859314fbfa1STim Northover case ConversionSpecifier::iArg:
860314fbfa1STim Northover case ConversionSpecifier::oArg:
861314fbfa1STim Northover case ConversionSpecifier::uArg:
862314fbfa1STim Northover case ConversionSpecifier::xArg:
863314fbfa1STim Northover case ConversionSpecifier::XArg:
864314fbfa1STim Northover return Target.getTriple().isOSMSVCRT();
865314fbfa1STim Northover default:
866314fbfa1STim Northover return false;
867314fbfa1STim Northover }
868314fbfa1STim Northover case LengthModifier::AsWide:
869314fbfa1STim Northover switch (CS.getKind()) {
870314fbfa1STim Northover case ConversionSpecifier::cArg:
871314fbfa1STim Northover case ConversionSpecifier::CArg:
872314fbfa1STim Northover case ConversionSpecifier::sArg:
873314fbfa1STim Northover case ConversionSpecifier::SArg:
874314fbfa1STim Northover case ConversionSpecifier::ZArg:
875314fbfa1STim Northover return Target.getTriple().isOSMSVCRT();
876314fbfa1STim Northover default:
877314fbfa1STim Northover return false;
878314fbfa1STim Northover }
879314fbfa1STim Northover }
880314fbfa1STim Northover llvm_unreachable("Invalid LengthModifier Kind!");
881314fbfa1STim Northover }
882314fbfa1STim Northover
hasStandardLengthModifier() const883314fbfa1STim Northover bool FormatSpecifier::hasStandardLengthModifier() const {
884314fbfa1STim Northover switch (LM.getKind()) {
885314fbfa1STim Northover case LengthModifier::None:
886314fbfa1STim Northover case LengthModifier::AsChar:
887314fbfa1STim Northover case LengthModifier::AsShort:
888314fbfa1STim Northover case LengthModifier::AsLong:
889314fbfa1STim Northover case LengthModifier::AsLongLong:
890314fbfa1STim Northover case LengthModifier::AsIntMax:
891314fbfa1STim Northover case LengthModifier::AsSizeT:
892314fbfa1STim Northover case LengthModifier::AsPtrDiff:
893314fbfa1STim Northover case LengthModifier::AsLongDouble:
894314fbfa1STim Northover return true;
895314fbfa1STim Northover case LengthModifier::AsAllocate:
896314fbfa1STim Northover case LengthModifier::AsMAllocate:
897314fbfa1STim Northover case LengthModifier::AsQuad:
898314fbfa1STim Northover case LengthModifier::AsInt32:
899314fbfa1STim Northover case LengthModifier::AsInt3264:
900314fbfa1STim Northover case LengthModifier::AsInt64:
901314fbfa1STim Northover case LengthModifier::AsWide:
90258fc8082SMatt Arsenault case LengthModifier::AsShortLong: // ???
903314fbfa1STim Northover return false;
904314fbfa1STim Northover }
905314fbfa1STim Northover llvm_unreachable("Invalid LengthModifier Kind!");
906314fbfa1STim Northover }
907314fbfa1STim Northover
hasStandardConversionSpecifier(const LangOptions & LangOpt) const908314fbfa1STim Northover bool FormatSpecifier::hasStandardConversionSpecifier(
909314fbfa1STim Northover const LangOptions &LangOpt) const {
910314fbfa1STim Northover switch (CS.getKind()) {
911314fbfa1STim Northover case ConversionSpecifier::cArg:
912314fbfa1STim Northover case ConversionSpecifier::dArg:
913314fbfa1STim Northover case ConversionSpecifier::iArg:
914314fbfa1STim Northover case ConversionSpecifier::oArg:
915314fbfa1STim Northover case ConversionSpecifier::uArg:
916314fbfa1STim Northover case ConversionSpecifier::xArg:
917314fbfa1STim Northover case ConversionSpecifier::XArg:
918314fbfa1STim Northover case ConversionSpecifier::fArg:
919314fbfa1STim Northover case ConversionSpecifier::FArg:
920314fbfa1STim Northover case ConversionSpecifier::eArg:
921314fbfa1STim Northover case ConversionSpecifier::EArg:
922314fbfa1STim Northover case ConversionSpecifier::gArg:
923314fbfa1STim Northover case ConversionSpecifier::GArg:
924314fbfa1STim Northover case ConversionSpecifier::aArg:
925314fbfa1STim Northover case ConversionSpecifier::AArg:
926314fbfa1STim Northover case ConversionSpecifier::sArg:
927314fbfa1STim Northover case ConversionSpecifier::pArg:
928314fbfa1STim Northover case ConversionSpecifier::nArg:
929314fbfa1STim Northover case ConversionSpecifier::ObjCObjArg:
930314fbfa1STim Northover case ConversionSpecifier::ScanListArg:
931314fbfa1STim Northover case ConversionSpecifier::PercentArg:
932314fbfa1STim Northover case ConversionSpecifier::PArg:
933314fbfa1STim Northover return true;
934314fbfa1STim Northover case ConversionSpecifier::CArg:
935314fbfa1STim Northover case ConversionSpecifier::SArg:
936314fbfa1STim Northover return LangOpt.ObjC;
937314fbfa1STim Northover case ConversionSpecifier::InvalidSpecifier:
938314fbfa1STim Northover case ConversionSpecifier::FreeBSDbArg:
939314fbfa1STim Northover case ConversionSpecifier::FreeBSDDArg:
940314fbfa1STim Northover case ConversionSpecifier::FreeBSDrArg:
941314fbfa1STim Northover case ConversionSpecifier::FreeBSDyArg:
942314fbfa1STim Northover case ConversionSpecifier::PrintErrno:
943314fbfa1STim Northover case ConversionSpecifier::DArg:
944314fbfa1STim Northover case ConversionSpecifier::OArg:
945314fbfa1STim Northover case ConversionSpecifier::UArg:
946314fbfa1STim Northover case ConversionSpecifier::ZArg:
947314fbfa1STim Northover return false;
948314fbfa1STim Northover }
949314fbfa1STim Northover llvm_unreachable("Invalid ConversionSpecifier Kind!");
950314fbfa1STim Northover }
951314fbfa1STim Northover
hasStandardLengthConversionCombination() const952314fbfa1STim Northover bool FormatSpecifier::hasStandardLengthConversionCombination() const {
953314fbfa1STim Northover if (LM.getKind() == LengthModifier::AsLongDouble) {
954314fbfa1STim Northover switch(CS.getKind()) {
955314fbfa1STim Northover case ConversionSpecifier::dArg:
956314fbfa1STim Northover case ConversionSpecifier::iArg:
957314fbfa1STim Northover case ConversionSpecifier::oArg:
958314fbfa1STim Northover case ConversionSpecifier::uArg:
959314fbfa1STim Northover case ConversionSpecifier::xArg:
960314fbfa1STim Northover case ConversionSpecifier::XArg:
961314fbfa1STim Northover return false;
962314fbfa1STim Northover default:
963314fbfa1STim Northover return true;
964314fbfa1STim Northover }
965314fbfa1STim Northover }
966314fbfa1STim Northover return true;
967314fbfa1STim Northover }
968314fbfa1STim Northover
getCorrectedLengthModifier() const969314fbfa1STim Northover Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
970314fbfa1STim Northover if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
971314fbfa1STim Northover if (LM.getKind() == LengthModifier::AsLongDouble ||
972314fbfa1STim Northover LM.getKind() == LengthModifier::AsQuad) {
973314fbfa1STim Northover LengthModifier FixedLM(LM);
974314fbfa1STim Northover FixedLM.setKind(LengthModifier::AsLongLong);
975314fbfa1STim Northover return FixedLM;
976314fbfa1STim Northover }
977314fbfa1STim Northover }
978314fbfa1STim Northover
979314fbfa1STim Northover return None;
980314fbfa1STim Northover }
981314fbfa1STim Northover
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)982314fbfa1STim Northover bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
983314fbfa1STim Northover LengthModifier &LM) {
984*888673b6SJonas Devlieghere assert(isa<TypedefType>(QT) && "Expected a TypedefType");
985*888673b6SJonas Devlieghere const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
986*888673b6SJonas Devlieghere
987*888673b6SJonas Devlieghere for (;;) {
988314fbfa1STim Northover const IdentifierInfo *Identifier = Typedef->getIdentifier();
989314fbfa1STim Northover if (Identifier->getName() == "size_t") {
990314fbfa1STim Northover LM.setKind(LengthModifier::AsSizeT);
991314fbfa1STim Northover return true;
992314fbfa1STim Northover } else if (Identifier->getName() == "ssize_t") {
993314fbfa1STim Northover // Not C99, but common in Unix.
994314fbfa1STim Northover LM.setKind(LengthModifier::AsSizeT);
995314fbfa1STim Northover return true;
996314fbfa1STim Northover } else if (Identifier->getName() == "intmax_t") {
997314fbfa1STim Northover LM.setKind(LengthModifier::AsIntMax);
998314fbfa1STim Northover return true;
999314fbfa1STim Northover } else if (Identifier->getName() == "uintmax_t") {
1000314fbfa1STim Northover LM.setKind(LengthModifier::AsIntMax);
1001314fbfa1STim Northover return true;
1002314fbfa1STim Northover } else if (Identifier->getName() == "ptrdiff_t") {
1003314fbfa1STim Northover LM.setKind(LengthModifier::AsPtrDiff);
1004314fbfa1STim Northover return true;
1005314fbfa1STim Northover }
1006*888673b6SJonas Devlieghere
1007*888673b6SJonas Devlieghere QualType T = Typedef->getUnderlyingType();
1008*888673b6SJonas Devlieghere if (!isa<TypedefType>(T))
1009*888673b6SJonas Devlieghere break;
1010*888673b6SJonas Devlieghere
1011*888673b6SJonas Devlieghere Typedef = cast<TypedefType>(T)->getDecl();
1012314fbfa1STim Northover }
1013314fbfa1STim Northover return false;
1014314fbfa1STim Northover }
1015