1f4a2713aSLionel Sambuc // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // Shared details for processing format strings of printf and scanf
11f4a2713aSLionel Sambuc // (and friends).
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "FormatStringParsing.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/LangOptions.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
18f4a2713aSLionel Sambuc
19f4a2713aSLionel Sambuc using clang::analyze_format_string::ArgType;
20f4a2713aSLionel Sambuc using clang::analyze_format_string::FormatStringHandler;
21f4a2713aSLionel Sambuc using clang::analyze_format_string::FormatSpecifier;
22f4a2713aSLionel Sambuc using clang::analyze_format_string::LengthModifier;
23f4a2713aSLionel Sambuc using clang::analyze_format_string::OptionalAmount;
24f4a2713aSLionel Sambuc using clang::analyze_format_string::PositionContext;
25f4a2713aSLionel Sambuc using clang::analyze_format_string::ConversionSpecifier;
26f4a2713aSLionel Sambuc using namespace clang;
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc // Key function to FormatStringHandler.
~FormatStringHandler()29f4a2713aSLionel Sambuc FormatStringHandler::~FormatStringHandler() {}
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
32f4a2713aSLionel Sambuc // Functions for parsing format strings components in both printf and
33f4a2713aSLionel Sambuc // scanf format strings.
34f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
35f4a2713aSLionel Sambuc
36f4a2713aSLionel Sambuc OptionalAmount
ParseAmount(const char * & Beg,const char * E)37f4a2713aSLionel Sambuc clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
38f4a2713aSLionel Sambuc const char *I = Beg;
39f4a2713aSLionel Sambuc UpdateOnReturn <const char*> UpdateBeg(Beg, I);
40f4a2713aSLionel Sambuc
41f4a2713aSLionel Sambuc unsigned accumulator = 0;
42f4a2713aSLionel Sambuc bool hasDigits = false;
43f4a2713aSLionel Sambuc
44f4a2713aSLionel Sambuc for ( ; I != E; ++I) {
45f4a2713aSLionel Sambuc char c = *I;
46f4a2713aSLionel Sambuc if (c >= '0' && c <= '9') {
47f4a2713aSLionel Sambuc hasDigits = true;
48f4a2713aSLionel Sambuc accumulator = (accumulator * 10) + (c - '0');
49f4a2713aSLionel Sambuc continue;
50f4a2713aSLionel Sambuc }
51f4a2713aSLionel Sambuc
52f4a2713aSLionel Sambuc if (hasDigits)
53f4a2713aSLionel Sambuc return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
54f4a2713aSLionel Sambuc false);
55f4a2713aSLionel Sambuc
56f4a2713aSLionel Sambuc break;
57f4a2713aSLionel Sambuc }
58f4a2713aSLionel Sambuc
59f4a2713aSLionel Sambuc return OptionalAmount();
60f4a2713aSLionel Sambuc }
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)63f4a2713aSLionel Sambuc clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
64f4a2713aSLionel Sambuc const char *E,
65f4a2713aSLionel Sambuc unsigned &argIndex) {
66f4a2713aSLionel Sambuc if (*Beg == '*') {
67f4a2713aSLionel Sambuc ++Beg;
68f4a2713aSLionel Sambuc return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
69f4a2713aSLionel Sambuc }
70f4a2713aSLionel Sambuc
71f4a2713aSLionel Sambuc return ParseAmount(Beg, E);
72f4a2713aSLionel Sambuc }
73f4a2713aSLionel Sambuc
74f4a2713aSLionel Sambuc OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)75f4a2713aSLionel Sambuc clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
76f4a2713aSLionel Sambuc const char *Start,
77f4a2713aSLionel Sambuc const char *&Beg,
78f4a2713aSLionel Sambuc const char *E,
79f4a2713aSLionel Sambuc PositionContext p) {
80f4a2713aSLionel Sambuc if (*Beg == '*') {
81f4a2713aSLionel Sambuc const char *I = Beg + 1;
82f4a2713aSLionel Sambuc const OptionalAmount &Amt = ParseAmount(I, E);
83f4a2713aSLionel Sambuc
84f4a2713aSLionel Sambuc if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
85f4a2713aSLionel Sambuc H.HandleInvalidPosition(Beg, I - Beg, p);
86f4a2713aSLionel Sambuc return OptionalAmount(false);
87f4a2713aSLionel Sambuc }
88f4a2713aSLionel Sambuc
89f4a2713aSLionel Sambuc if (I == E) {
90f4a2713aSLionel Sambuc // No more characters left?
91f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
92f4a2713aSLionel Sambuc return OptionalAmount(false);
93f4a2713aSLionel Sambuc }
94f4a2713aSLionel Sambuc
95f4a2713aSLionel Sambuc assert(Amt.getHowSpecified() == OptionalAmount::Constant);
96f4a2713aSLionel Sambuc
97f4a2713aSLionel Sambuc if (*I == '$') {
98f4a2713aSLionel Sambuc // Handle positional arguments
99f4a2713aSLionel Sambuc
100f4a2713aSLionel Sambuc // Special case: '*0$', since this is an easy mistake.
101f4a2713aSLionel Sambuc if (Amt.getConstantAmount() == 0) {
102f4a2713aSLionel Sambuc H.HandleZeroPosition(Beg, I - Beg + 1);
103f4a2713aSLionel Sambuc return OptionalAmount(false);
104f4a2713aSLionel Sambuc }
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc const char *Tmp = Beg;
107f4a2713aSLionel Sambuc Beg = ++I;
108f4a2713aSLionel Sambuc
109f4a2713aSLionel Sambuc return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
110f4a2713aSLionel Sambuc Tmp, 0, true);
111f4a2713aSLionel Sambuc }
112f4a2713aSLionel Sambuc
113f4a2713aSLionel Sambuc H.HandleInvalidPosition(Beg, I - Beg, p);
114f4a2713aSLionel Sambuc return OptionalAmount(false);
115f4a2713aSLionel Sambuc }
116f4a2713aSLionel Sambuc
117f4a2713aSLionel Sambuc return ParseAmount(Beg, E);
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc
120f4a2713aSLionel Sambuc
121f4a2713aSLionel Sambuc bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)122f4a2713aSLionel Sambuc clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
123f4a2713aSLionel Sambuc FormatSpecifier &CS,
124f4a2713aSLionel Sambuc const char *Start,
125f4a2713aSLionel Sambuc const char *&Beg, const char *E,
126f4a2713aSLionel Sambuc unsigned *argIndex) {
127f4a2713aSLionel Sambuc // FIXME: Support negative field widths.
128f4a2713aSLionel Sambuc if (argIndex) {
129f4a2713aSLionel Sambuc CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc else {
132f4a2713aSLionel Sambuc const OptionalAmount Amt =
133f4a2713aSLionel Sambuc ParsePositionAmount(H, Start, Beg, E,
134f4a2713aSLionel Sambuc analyze_format_string::FieldWidthPos);
135f4a2713aSLionel Sambuc
136f4a2713aSLionel Sambuc if (Amt.isInvalid())
137f4a2713aSLionel Sambuc return true;
138f4a2713aSLionel Sambuc CS.setFieldWidth(Amt);
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc return false;
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc
143f4a2713aSLionel Sambuc bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)144f4a2713aSLionel Sambuc clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
145f4a2713aSLionel Sambuc FormatSpecifier &FS,
146f4a2713aSLionel Sambuc const char *Start,
147f4a2713aSLionel Sambuc const char *&Beg,
148f4a2713aSLionel Sambuc const char *E) {
149f4a2713aSLionel Sambuc const char *I = Beg;
150f4a2713aSLionel Sambuc
151f4a2713aSLionel Sambuc const OptionalAmount &Amt = ParseAmount(I, E);
152f4a2713aSLionel Sambuc
153f4a2713aSLionel Sambuc if (I == E) {
154f4a2713aSLionel Sambuc // No more characters left?
155f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
156f4a2713aSLionel Sambuc return true;
157f4a2713aSLionel Sambuc }
158f4a2713aSLionel Sambuc
159f4a2713aSLionel Sambuc if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
160f4a2713aSLionel Sambuc // Warn that positional arguments are non-standard.
161f4a2713aSLionel Sambuc H.HandlePosition(Start, I - Start);
162f4a2713aSLionel Sambuc
163f4a2713aSLionel Sambuc // Special case: '%0$', since this is an easy mistake.
164f4a2713aSLionel Sambuc if (Amt.getConstantAmount() == 0) {
165f4a2713aSLionel Sambuc H.HandleZeroPosition(Start, I - Start);
166f4a2713aSLionel Sambuc return true;
167f4a2713aSLionel Sambuc }
168f4a2713aSLionel Sambuc
169f4a2713aSLionel Sambuc FS.setArgIndex(Amt.getConstantAmount() - 1);
170f4a2713aSLionel Sambuc FS.setUsesPositionalArg();
171f4a2713aSLionel Sambuc // Update the caller's pointer if we decided to consume
172f4a2713aSLionel Sambuc // these characters.
173f4a2713aSLionel Sambuc Beg = I;
174f4a2713aSLionel Sambuc return false;
175f4a2713aSLionel Sambuc }
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc return false;
178f4a2713aSLionel Sambuc }
179f4a2713aSLionel Sambuc
180f4a2713aSLionel Sambuc bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)181f4a2713aSLionel Sambuc clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
182f4a2713aSLionel Sambuc const char *&I,
183f4a2713aSLionel Sambuc const char *E,
184f4a2713aSLionel Sambuc const LangOptions &LO,
185f4a2713aSLionel Sambuc bool IsScanf) {
186f4a2713aSLionel Sambuc LengthModifier::Kind lmKind = LengthModifier::None;
187f4a2713aSLionel Sambuc const char *lmPosition = I;
188f4a2713aSLionel Sambuc switch (*I) {
189f4a2713aSLionel Sambuc default:
190f4a2713aSLionel Sambuc return false;
191f4a2713aSLionel Sambuc case 'h':
192f4a2713aSLionel Sambuc ++I;
193f4a2713aSLionel Sambuc lmKind = (I != E && *I == 'h') ? (++I, LengthModifier::AsChar)
194f4a2713aSLionel Sambuc : LengthModifier::AsShort;
195f4a2713aSLionel Sambuc break;
196f4a2713aSLionel Sambuc case 'l':
197f4a2713aSLionel Sambuc ++I;
198f4a2713aSLionel Sambuc lmKind = (I != E && *I == 'l') ? (++I, LengthModifier::AsLongLong)
199f4a2713aSLionel Sambuc : LengthModifier::AsLong;
200f4a2713aSLionel Sambuc break;
201f4a2713aSLionel Sambuc case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
202f4a2713aSLionel Sambuc case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
203f4a2713aSLionel Sambuc case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
204f4a2713aSLionel Sambuc case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
205f4a2713aSLionel Sambuc case 'q': lmKind = LengthModifier::AsQuad; ++I; break;
206f4a2713aSLionel Sambuc case 'a':
207f4a2713aSLionel Sambuc if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
208f4a2713aSLionel Sambuc // For scanf in C90, look at the next character to see if this should
209f4a2713aSLionel Sambuc // be parsed as the GNU extension 'a' length modifier. If not, this
210f4a2713aSLionel Sambuc // will be parsed as a conversion specifier.
211f4a2713aSLionel Sambuc ++I;
212f4a2713aSLionel Sambuc if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
213f4a2713aSLionel Sambuc lmKind = LengthModifier::AsAllocate;
214f4a2713aSLionel Sambuc break;
215f4a2713aSLionel Sambuc }
216f4a2713aSLionel Sambuc --I;
217f4a2713aSLionel Sambuc }
218f4a2713aSLionel Sambuc return false;
219f4a2713aSLionel Sambuc case 'm':
220f4a2713aSLionel Sambuc if (IsScanf) {
221f4a2713aSLionel Sambuc lmKind = LengthModifier::AsMAllocate;
222f4a2713aSLionel Sambuc ++I;
223f4a2713aSLionel Sambuc break;
224f4a2713aSLionel Sambuc }
225f4a2713aSLionel Sambuc return false;
226f4a2713aSLionel Sambuc // printf: AsInt64, AsInt32, AsInt3264
227f4a2713aSLionel Sambuc // scanf: AsInt64
228f4a2713aSLionel Sambuc case 'I':
229f4a2713aSLionel Sambuc if (I + 1 != E && I + 2 != E) {
230f4a2713aSLionel Sambuc if (I[1] == '6' && I[2] == '4') {
231f4a2713aSLionel Sambuc I += 3;
232f4a2713aSLionel Sambuc lmKind = LengthModifier::AsInt64;
233f4a2713aSLionel Sambuc break;
234f4a2713aSLionel Sambuc }
235f4a2713aSLionel Sambuc if (IsScanf)
236f4a2713aSLionel Sambuc return false;
237f4a2713aSLionel Sambuc
238f4a2713aSLionel Sambuc if (I[1] == '3' && I[2] == '2') {
239f4a2713aSLionel Sambuc I += 3;
240f4a2713aSLionel Sambuc lmKind = LengthModifier::AsInt32;
241f4a2713aSLionel Sambuc break;
242f4a2713aSLionel Sambuc }
243f4a2713aSLionel Sambuc }
244f4a2713aSLionel Sambuc ++I;
245f4a2713aSLionel Sambuc lmKind = LengthModifier::AsInt3264;
246f4a2713aSLionel Sambuc break;
247*0a6a1f1dSLionel Sambuc case 'w':
248*0a6a1f1dSLionel Sambuc lmKind = LengthModifier::AsWide; ++I; break;
249f4a2713aSLionel Sambuc }
250f4a2713aSLionel Sambuc LengthModifier lm(lmPosition, lmKind);
251f4a2713aSLionel Sambuc FS.setLengthModifier(lm);
252f4a2713aSLionel Sambuc return true;
253f4a2713aSLionel Sambuc }
254f4a2713aSLionel Sambuc
255f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
256f4a2713aSLionel Sambuc // Methods on ArgType.
257f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
258f4a2713aSLionel Sambuc
matchesType(ASTContext & C,QualType argTy) const259f4a2713aSLionel Sambuc bool ArgType::matchesType(ASTContext &C, QualType argTy) const {
260f4a2713aSLionel Sambuc if (Ptr) {
261f4a2713aSLionel Sambuc // It has to be a pointer.
262f4a2713aSLionel Sambuc const PointerType *PT = argTy->getAs<PointerType>();
263f4a2713aSLionel Sambuc if (!PT)
264f4a2713aSLionel Sambuc return false;
265f4a2713aSLionel Sambuc
266f4a2713aSLionel Sambuc // We cannot write through a const qualified pointer.
267f4a2713aSLionel Sambuc if (PT->getPointeeType().isConstQualified())
268f4a2713aSLionel Sambuc return false;
269f4a2713aSLionel Sambuc
270f4a2713aSLionel Sambuc argTy = PT->getPointeeType();
271f4a2713aSLionel Sambuc }
272f4a2713aSLionel Sambuc
273f4a2713aSLionel Sambuc switch (K) {
274f4a2713aSLionel Sambuc case InvalidTy:
275f4a2713aSLionel Sambuc llvm_unreachable("ArgType must be valid");
276f4a2713aSLionel Sambuc
277f4a2713aSLionel Sambuc case UnknownTy:
278f4a2713aSLionel Sambuc return true;
279f4a2713aSLionel Sambuc
280f4a2713aSLionel Sambuc case AnyCharTy: {
281f4a2713aSLionel Sambuc if (const EnumType *ETy = argTy->getAs<EnumType>())
282f4a2713aSLionel Sambuc argTy = ETy->getDecl()->getIntegerType();
283f4a2713aSLionel Sambuc
284f4a2713aSLionel Sambuc if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
285f4a2713aSLionel Sambuc switch (BT->getKind()) {
286f4a2713aSLionel Sambuc default:
287f4a2713aSLionel Sambuc break;
288f4a2713aSLionel Sambuc case BuiltinType::Char_S:
289f4a2713aSLionel Sambuc case BuiltinType::SChar:
290f4a2713aSLionel Sambuc case BuiltinType::UChar:
291f4a2713aSLionel Sambuc case BuiltinType::Char_U:
292f4a2713aSLionel Sambuc return true;
293f4a2713aSLionel Sambuc }
294f4a2713aSLionel Sambuc return false;
295f4a2713aSLionel Sambuc }
296f4a2713aSLionel Sambuc
297f4a2713aSLionel Sambuc case SpecificTy: {
298f4a2713aSLionel Sambuc if (const EnumType *ETy = argTy->getAs<EnumType>())
299f4a2713aSLionel Sambuc argTy = ETy->getDecl()->getIntegerType();
300f4a2713aSLionel Sambuc argTy = C.getCanonicalType(argTy).getUnqualifiedType();
301f4a2713aSLionel Sambuc
302f4a2713aSLionel Sambuc if (T == argTy)
303f4a2713aSLionel Sambuc return true;
304f4a2713aSLionel Sambuc // Check for "compatible types".
305f4a2713aSLionel Sambuc if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
306f4a2713aSLionel Sambuc switch (BT->getKind()) {
307f4a2713aSLionel Sambuc default:
308f4a2713aSLionel Sambuc break;
309f4a2713aSLionel Sambuc case BuiltinType::Char_S:
310f4a2713aSLionel Sambuc case BuiltinType::SChar:
311f4a2713aSLionel Sambuc case BuiltinType::Char_U:
312f4a2713aSLionel Sambuc case BuiltinType::UChar:
313f4a2713aSLionel Sambuc return T == C.UnsignedCharTy || T == C.SignedCharTy;
314f4a2713aSLionel Sambuc case BuiltinType::Short:
315f4a2713aSLionel Sambuc return T == C.UnsignedShortTy;
316f4a2713aSLionel Sambuc case BuiltinType::UShort:
317f4a2713aSLionel Sambuc return T == C.ShortTy;
318f4a2713aSLionel Sambuc case BuiltinType::Int:
319f4a2713aSLionel Sambuc return T == C.UnsignedIntTy;
320f4a2713aSLionel Sambuc case BuiltinType::UInt:
321f4a2713aSLionel Sambuc return T == C.IntTy;
322f4a2713aSLionel Sambuc case BuiltinType::Long:
323f4a2713aSLionel Sambuc return T == C.UnsignedLongTy;
324f4a2713aSLionel Sambuc case BuiltinType::ULong:
325f4a2713aSLionel Sambuc return T == C.LongTy;
326f4a2713aSLionel Sambuc case BuiltinType::LongLong:
327f4a2713aSLionel Sambuc return T == C.UnsignedLongLongTy;
328f4a2713aSLionel Sambuc case BuiltinType::ULongLong:
329f4a2713aSLionel Sambuc return T == C.LongLongTy;
330f4a2713aSLionel Sambuc }
331f4a2713aSLionel Sambuc return false;
332f4a2713aSLionel Sambuc }
333f4a2713aSLionel Sambuc
334f4a2713aSLionel Sambuc case CStrTy: {
335f4a2713aSLionel Sambuc const PointerType *PT = argTy->getAs<PointerType>();
336f4a2713aSLionel Sambuc if (!PT)
337f4a2713aSLionel Sambuc return false;
338f4a2713aSLionel Sambuc QualType pointeeTy = PT->getPointeeType();
339f4a2713aSLionel Sambuc if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
340f4a2713aSLionel Sambuc switch (BT->getKind()) {
341f4a2713aSLionel Sambuc case BuiltinType::Void:
342f4a2713aSLionel Sambuc case BuiltinType::Char_U:
343f4a2713aSLionel Sambuc case BuiltinType::UChar:
344f4a2713aSLionel Sambuc case BuiltinType::Char_S:
345f4a2713aSLionel Sambuc case BuiltinType::SChar:
346f4a2713aSLionel Sambuc return true;
347f4a2713aSLionel Sambuc default:
348f4a2713aSLionel Sambuc break;
349f4a2713aSLionel Sambuc }
350f4a2713aSLionel Sambuc
351f4a2713aSLionel Sambuc return false;
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc
354f4a2713aSLionel Sambuc case WCStrTy: {
355f4a2713aSLionel Sambuc const PointerType *PT = argTy->getAs<PointerType>();
356f4a2713aSLionel Sambuc if (!PT)
357f4a2713aSLionel Sambuc return false;
358f4a2713aSLionel Sambuc QualType pointeeTy =
359f4a2713aSLionel Sambuc C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
360f4a2713aSLionel Sambuc return pointeeTy == C.getWideCharType();
361f4a2713aSLionel Sambuc }
362f4a2713aSLionel Sambuc
363f4a2713aSLionel Sambuc case WIntTy: {
364f4a2713aSLionel Sambuc
365f4a2713aSLionel Sambuc QualType PromoArg =
366f4a2713aSLionel Sambuc argTy->isPromotableIntegerType()
367f4a2713aSLionel Sambuc ? C.getPromotedIntegerType(argTy) : argTy;
368f4a2713aSLionel Sambuc
369f4a2713aSLionel Sambuc QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
370f4a2713aSLionel Sambuc PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
371f4a2713aSLionel Sambuc
372f4a2713aSLionel Sambuc // If the promoted argument is the corresponding signed type of the
373f4a2713aSLionel Sambuc // wint_t type, then it should match.
374f4a2713aSLionel Sambuc if (PromoArg->hasSignedIntegerRepresentation() &&
375f4a2713aSLionel Sambuc C.getCorrespondingUnsignedType(PromoArg) == WInt)
376f4a2713aSLionel Sambuc return true;
377f4a2713aSLionel Sambuc
378f4a2713aSLionel Sambuc return WInt == PromoArg;
379f4a2713aSLionel Sambuc }
380f4a2713aSLionel Sambuc
381f4a2713aSLionel Sambuc case CPointerTy:
382f4a2713aSLionel Sambuc return argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
383f4a2713aSLionel Sambuc argTy->isBlockPointerType() || argTy->isNullPtrType();
384f4a2713aSLionel Sambuc
385f4a2713aSLionel Sambuc case ObjCPointerTy: {
386f4a2713aSLionel Sambuc if (argTy->getAs<ObjCObjectPointerType>() ||
387f4a2713aSLionel Sambuc argTy->getAs<BlockPointerType>())
388f4a2713aSLionel Sambuc return true;
389f4a2713aSLionel Sambuc
390f4a2713aSLionel Sambuc // Handle implicit toll-free bridging.
391f4a2713aSLionel Sambuc if (const PointerType *PT = argTy->getAs<PointerType>()) {
392f4a2713aSLionel Sambuc // Things such as CFTypeRef are really just opaque pointers
393f4a2713aSLionel Sambuc // to C structs representing CF types that can often be bridged
394f4a2713aSLionel Sambuc // to Objective-C objects. Since the compiler doesn't know which
395f4a2713aSLionel Sambuc // structs can be toll-free bridged, we just accept them all.
396f4a2713aSLionel Sambuc QualType pointee = PT->getPointeeType();
397f4a2713aSLionel Sambuc if (pointee->getAsStructureType() || pointee->isVoidType())
398f4a2713aSLionel Sambuc return true;
399f4a2713aSLionel Sambuc }
400f4a2713aSLionel Sambuc return false;
401f4a2713aSLionel Sambuc }
402f4a2713aSLionel Sambuc }
403f4a2713aSLionel Sambuc
404f4a2713aSLionel Sambuc llvm_unreachable("Invalid ArgType Kind!");
405f4a2713aSLionel Sambuc }
406f4a2713aSLionel Sambuc
getRepresentativeType(ASTContext & C) const407f4a2713aSLionel Sambuc QualType ArgType::getRepresentativeType(ASTContext &C) const {
408f4a2713aSLionel Sambuc QualType Res;
409f4a2713aSLionel Sambuc switch (K) {
410f4a2713aSLionel Sambuc case InvalidTy:
411f4a2713aSLionel Sambuc llvm_unreachable("No representative type for Invalid ArgType");
412f4a2713aSLionel Sambuc case UnknownTy:
413f4a2713aSLionel Sambuc llvm_unreachable("No representative type for Unknown ArgType");
414f4a2713aSLionel Sambuc case AnyCharTy:
415f4a2713aSLionel Sambuc Res = C.CharTy;
416f4a2713aSLionel Sambuc break;
417f4a2713aSLionel Sambuc case SpecificTy:
418f4a2713aSLionel Sambuc Res = T;
419f4a2713aSLionel Sambuc break;
420f4a2713aSLionel Sambuc case CStrTy:
421f4a2713aSLionel Sambuc Res = C.getPointerType(C.CharTy);
422f4a2713aSLionel Sambuc break;
423f4a2713aSLionel Sambuc case WCStrTy:
424f4a2713aSLionel Sambuc Res = C.getPointerType(C.getWideCharType());
425f4a2713aSLionel Sambuc break;
426f4a2713aSLionel Sambuc case ObjCPointerTy:
427f4a2713aSLionel Sambuc Res = C.ObjCBuiltinIdTy;
428f4a2713aSLionel Sambuc break;
429f4a2713aSLionel Sambuc case CPointerTy:
430f4a2713aSLionel Sambuc Res = C.VoidPtrTy;
431f4a2713aSLionel Sambuc break;
432f4a2713aSLionel Sambuc case WIntTy: {
433f4a2713aSLionel Sambuc Res = C.getWIntType();
434f4a2713aSLionel Sambuc break;
435f4a2713aSLionel Sambuc }
436f4a2713aSLionel Sambuc }
437f4a2713aSLionel Sambuc
438f4a2713aSLionel Sambuc if (Ptr)
439f4a2713aSLionel Sambuc Res = C.getPointerType(Res);
440f4a2713aSLionel Sambuc return Res;
441f4a2713aSLionel Sambuc }
442f4a2713aSLionel Sambuc
getRepresentativeTypeName(ASTContext & C) const443f4a2713aSLionel Sambuc std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
444f4a2713aSLionel Sambuc std::string S = getRepresentativeType(C).getAsString();
445f4a2713aSLionel Sambuc
446f4a2713aSLionel Sambuc std::string Alias;
447f4a2713aSLionel Sambuc if (Name) {
448f4a2713aSLionel Sambuc // Use a specific name for this type, e.g. "size_t".
449f4a2713aSLionel Sambuc Alias = Name;
450f4a2713aSLionel Sambuc if (Ptr) {
451f4a2713aSLionel Sambuc // If ArgType is actually a pointer to T, append an asterisk.
452f4a2713aSLionel Sambuc Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
453f4a2713aSLionel Sambuc }
454f4a2713aSLionel Sambuc // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
455f4a2713aSLionel Sambuc if (S == Alias)
456f4a2713aSLionel Sambuc Alias.clear();
457f4a2713aSLionel Sambuc }
458f4a2713aSLionel Sambuc
459f4a2713aSLionel Sambuc if (!Alias.empty())
460f4a2713aSLionel Sambuc return std::string("'") + Alias + "' (aka '" + S + "')";
461f4a2713aSLionel Sambuc return std::string("'") + S + "'";
462f4a2713aSLionel Sambuc }
463f4a2713aSLionel Sambuc
464f4a2713aSLionel Sambuc
465f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
466f4a2713aSLionel Sambuc // Methods on OptionalAmount.
467f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
468f4a2713aSLionel Sambuc
469f4a2713aSLionel Sambuc ArgType
getArgType(ASTContext & Ctx) const470f4a2713aSLionel Sambuc analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
471f4a2713aSLionel Sambuc return Ctx.IntTy;
472f4a2713aSLionel Sambuc }
473f4a2713aSLionel Sambuc
474f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
475f4a2713aSLionel Sambuc // Methods on LengthModifier.
476f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
477f4a2713aSLionel Sambuc
478f4a2713aSLionel Sambuc const char *
toString() const479f4a2713aSLionel Sambuc analyze_format_string::LengthModifier::toString() const {
480f4a2713aSLionel Sambuc switch (kind) {
481f4a2713aSLionel Sambuc case AsChar:
482f4a2713aSLionel Sambuc return "hh";
483f4a2713aSLionel Sambuc case AsShort:
484f4a2713aSLionel Sambuc return "h";
485f4a2713aSLionel Sambuc case AsLong: // or AsWideChar
486f4a2713aSLionel Sambuc return "l";
487f4a2713aSLionel Sambuc case AsLongLong:
488f4a2713aSLionel Sambuc return "ll";
489f4a2713aSLionel Sambuc case AsQuad:
490f4a2713aSLionel Sambuc return "q";
491f4a2713aSLionel Sambuc case AsIntMax:
492f4a2713aSLionel Sambuc return "j";
493f4a2713aSLionel Sambuc case AsSizeT:
494f4a2713aSLionel Sambuc return "z";
495f4a2713aSLionel Sambuc case AsPtrDiff:
496f4a2713aSLionel Sambuc return "t";
497f4a2713aSLionel Sambuc case AsInt32:
498f4a2713aSLionel Sambuc return "I32";
499f4a2713aSLionel Sambuc case AsInt3264:
500f4a2713aSLionel Sambuc return "I";
501f4a2713aSLionel Sambuc case AsInt64:
502f4a2713aSLionel Sambuc return "I64";
503f4a2713aSLionel Sambuc case AsLongDouble:
504f4a2713aSLionel Sambuc return "L";
505f4a2713aSLionel Sambuc case AsAllocate:
506f4a2713aSLionel Sambuc return "a";
507f4a2713aSLionel Sambuc case AsMAllocate:
508f4a2713aSLionel Sambuc return "m";
509*0a6a1f1dSLionel Sambuc case AsWide:
510*0a6a1f1dSLionel Sambuc return "w";
511f4a2713aSLionel Sambuc case None:
512f4a2713aSLionel Sambuc return "";
513f4a2713aSLionel Sambuc }
514*0a6a1f1dSLionel Sambuc return nullptr;
515f4a2713aSLionel Sambuc }
516f4a2713aSLionel Sambuc
517f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
518f4a2713aSLionel Sambuc // Methods on ConversionSpecifier.
519f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
520f4a2713aSLionel Sambuc
toString() const521f4a2713aSLionel Sambuc const char *ConversionSpecifier::toString() const {
522f4a2713aSLionel Sambuc switch (kind) {
523f4a2713aSLionel Sambuc case dArg: return "d";
524f4a2713aSLionel Sambuc case DArg: return "D";
525f4a2713aSLionel Sambuc case iArg: return "i";
526f4a2713aSLionel Sambuc case oArg: return "o";
527f4a2713aSLionel Sambuc case OArg: return "O";
528f4a2713aSLionel Sambuc case uArg: return "u";
529f4a2713aSLionel Sambuc case UArg: return "U";
530f4a2713aSLionel Sambuc case xArg: return "x";
531f4a2713aSLionel Sambuc case XArg: return "X";
532f4a2713aSLionel Sambuc case fArg: return "f";
533f4a2713aSLionel Sambuc case FArg: return "F";
534f4a2713aSLionel Sambuc case eArg: return "e";
535f4a2713aSLionel Sambuc case EArg: return "E";
536f4a2713aSLionel Sambuc case gArg: return "g";
537f4a2713aSLionel Sambuc case GArg: return "G";
538f4a2713aSLionel Sambuc case aArg: return "a";
539f4a2713aSLionel Sambuc case AArg: return "A";
540f4a2713aSLionel Sambuc case cArg: return "c";
541f4a2713aSLionel Sambuc case sArg: return "s";
542f4a2713aSLionel Sambuc case pArg: return "p";
543f4a2713aSLionel Sambuc case nArg: return "n";
544f4a2713aSLionel Sambuc case PercentArg: return "%";
545f4a2713aSLionel Sambuc case ScanListArg: return "[";
546*0a6a1f1dSLionel Sambuc case InvalidSpecifier: return nullptr;
547f4a2713aSLionel Sambuc
548f4a2713aSLionel Sambuc // POSIX unicode extensions.
549f4a2713aSLionel Sambuc case CArg: return "C";
550f4a2713aSLionel Sambuc case SArg: return "S";
551f4a2713aSLionel Sambuc
552f4a2713aSLionel Sambuc // Objective-C specific specifiers.
553f4a2713aSLionel Sambuc case ObjCObjArg: return "@";
554f4a2713aSLionel Sambuc
555f4a2713aSLionel Sambuc // GlibC specific specifiers.
556f4a2713aSLionel Sambuc case PrintErrno: return "m";
557*0a6a1f1dSLionel Sambuc
558*0a6a1f1dSLionel Sambuc // MS specific specifiers.
559*0a6a1f1dSLionel Sambuc case ZArg: return "Z";
560f4a2713aSLionel Sambuc }
561*0a6a1f1dSLionel Sambuc return nullptr;
562f4a2713aSLionel Sambuc }
563f4a2713aSLionel Sambuc
564f4a2713aSLionel Sambuc Optional<ConversionSpecifier>
getStandardSpecifier() const565f4a2713aSLionel Sambuc ConversionSpecifier::getStandardSpecifier() const {
566f4a2713aSLionel Sambuc ConversionSpecifier::Kind NewKind;
567f4a2713aSLionel Sambuc
568f4a2713aSLionel Sambuc switch (getKind()) {
569f4a2713aSLionel Sambuc default:
570f4a2713aSLionel Sambuc return None;
571f4a2713aSLionel Sambuc case DArg:
572f4a2713aSLionel Sambuc NewKind = dArg;
573f4a2713aSLionel Sambuc break;
574f4a2713aSLionel Sambuc case UArg:
575f4a2713aSLionel Sambuc NewKind = uArg;
576f4a2713aSLionel Sambuc break;
577f4a2713aSLionel Sambuc case OArg:
578f4a2713aSLionel Sambuc NewKind = oArg;
579f4a2713aSLionel Sambuc break;
580f4a2713aSLionel Sambuc }
581f4a2713aSLionel Sambuc
582f4a2713aSLionel Sambuc ConversionSpecifier FixedCS(*this);
583f4a2713aSLionel Sambuc FixedCS.setKind(NewKind);
584f4a2713aSLionel Sambuc return FixedCS;
585f4a2713aSLionel Sambuc }
586f4a2713aSLionel Sambuc
587f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
588f4a2713aSLionel Sambuc // Methods on OptionalAmount.
589f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
590f4a2713aSLionel Sambuc
toString(raw_ostream & os) const591f4a2713aSLionel Sambuc void OptionalAmount::toString(raw_ostream &os) const {
592f4a2713aSLionel Sambuc switch (hs) {
593f4a2713aSLionel Sambuc case Invalid:
594f4a2713aSLionel Sambuc case NotSpecified:
595f4a2713aSLionel Sambuc return;
596f4a2713aSLionel Sambuc case Arg:
597f4a2713aSLionel Sambuc if (UsesDotPrefix)
598f4a2713aSLionel Sambuc os << ".";
599f4a2713aSLionel Sambuc if (usesPositionalArg())
600f4a2713aSLionel Sambuc os << "*" << getPositionalArgIndex() << "$";
601f4a2713aSLionel Sambuc else
602f4a2713aSLionel Sambuc os << "*";
603f4a2713aSLionel Sambuc break;
604f4a2713aSLionel Sambuc case Constant:
605f4a2713aSLionel Sambuc if (UsesDotPrefix)
606f4a2713aSLionel Sambuc os << ".";
607f4a2713aSLionel Sambuc os << amt;
608f4a2713aSLionel Sambuc break;
609f4a2713aSLionel Sambuc }
610f4a2713aSLionel Sambuc }
611f4a2713aSLionel Sambuc
hasValidLengthModifier(const TargetInfo & Target) const612f4a2713aSLionel Sambuc bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
613f4a2713aSLionel Sambuc switch (LM.getKind()) {
614f4a2713aSLionel Sambuc case LengthModifier::None:
615f4a2713aSLionel Sambuc return true;
616f4a2713aSLionel Sambuc
617f4a2713aSLionel Sambuc // Handle most integer flags
618f4a2713aSLionel Sambuc case LengthModifier::AsShort:
619*0a6a1f1dSLionel Sambuc if (Target.getTriple().isOSMSVCRT()) {
620*0a6a1f1dSLionel Sambuc switch (CS.getKind()) {
621*0a6a1f1dSLionel Sambuc case ConversionSpecifier::cArg:
622*0a6a1f1dSLionel Sambuc case ConversionSpecifier::CArg:
623*0a6a1f1dSLionel Sambuc case ConversionSpecifier::sArg:
624*0a6a1f1dSLionel Sambuc case ConversionSpecifier::SArg:
625*0a6a1f1dSLionel Sambuc case ConversionSpecifier::ZArg:
626*0a6a1f1dSLionel Sambuc return true;
627*0a6a1f1dSLionel Sambuc default:
628*0a6a1f1dSLionel Sambuc break;
629*0a6a1f1dSLionel Sambuc }
630*0a6a1f1dSLionel Sambuc }
631*0a6a1f1dSLionel Sambuc // Fall through.
632*0a6a1f1dSLionel Sambuc case LengthModifier::AsChar:
633f4a2713aSLionel Sambuc case LengthModifier::AsLongLong:
634f4a2713aSLionel Sambuc case LengthModifier::AsQuad:
635f4a2713aSLionel Sambuc case LengthModifier::AsIntMax:
636f4a2713aSLionel Sambuc case LengthModifier::AsSizeT:
637f4a2713aSLionel Sambuc case LengthModifier::AsPtrDiff:
638f4a2713aSLionel Sambuc switch (CS.getKind()) {
639f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
640f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
641f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
642f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
643f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
644f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
645f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
646f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
647f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
648f4a2713aSLionel Sambuc case ConversionSpecifier::nArg:
649f4a2713aSLionel Sambuc return true;
650f4a2713aSLionel Sambuc default:
651f4a2713aSLionel Sambuc return false;
652f4a2713aSLionel Sambuc }
653f4a2713aSLionel Sambuc
654f4a2713aSLionel Sambuc // Handle 'l' flag
655*0a6a1f1dSLionel Sambuc case LengthModifier::AsLong: // or AsWideChar
656f4a2713aSLionel Sambuc switch (CS.getKind()) {
657f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
658f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
659f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
660f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
661f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
662f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
663f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
664f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
665f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
666f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
667f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
668f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
669f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
670f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
671f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
672f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
673f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
674f4a2713aSLionel Sambuc case ConversionSpecifier::nArg:
675f4a2713aSLionel Sambuc case ConversionSpecifier::cArg:
676f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
677f4a2713aSLionel Sambuc case ConversionSpecifier::ScanListArg:
678*0a6a1f1dSLionel Sambuc case ConversionSpecifier::ZArg:
679f4a2713aSLionel Sambuc return true;
680f4a2713aSLionel Sambuc default:
681f4a2713aSLionel Sambuc return false;
682f4a2713aSLionel Sambuc }
683f4a2713aSLionel Sambuc
684f4a2713aSLionel Sambuc case LengthModifier::AsLongDouble:
685f4a2713aSLionel Sambuc switch (CS.getKind()) {
686f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
687f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
688f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
689f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
690f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
691f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
692f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
693f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
694f4a2713aSLionel Sambuc return true;
695f4a2713aSLionel Sambuc // GNU libc extension.
696f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
697f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
698f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
699f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
700f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
701f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
702f4a2713aSLionel Sambuc return !Target.getTriple().isOSDarwin() &&
703f4a2713aSLionel Sambuc !Target.getTriple().isOSWindows();
704f4a2713aSLionel Sambuc default:
705f4a2713aSLionel Sambuc return false;
706f4a2713aSLionel Sambuc }
707f4a2713aSLionel Sambuc
708f4a2713aSLionel Sambuc case LengthModifier::AsAllocate:
709f4a2713aSLionel Sambuc switch (CS.getKind()) {
710f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
711f4a2713aSLionel Sambuc case ConversionSpecifier::SArg:
712f4a2713aSLionel Sambuc case ConversionSpecifier::ScanListArg:
713f4a2713aSLionel Sambuc return true;
714f4a2713aSLionel Sambuc default:
715f4a2713aSLionel Sambuc return false;
716f4a2713aSLionel Sambuc }
717f4a2713aSLionel Sambuc
718f4a2713aSLionel Sambuc case LengthModifier::AsMAllocate:
719f4a2713aSLionel Sambuc switch (CS.getKind()) {
720f4a2713aSLionel Sambuc case ConversionSpecifier::cArg:
721f4a2713aSLionel Sambuc case ConversionSpecifier::CArg:
722f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
723f4a2713aSLionel Sambuc case ConversionSpecifier::SArg:
724f4a2713aSLionel Sambuc case ConversionSpecifier::ScanListArg:
725f4a2713aSLionel Sambuc return true;
726f4a2713aSLionel Sambuc default:
727f4a2713aSLionel Sambuc return false;
728f4a2713aSLionel Sambuc }
729f4a2713aSLionel Sambuc case LengthModifier::AsInt32:
730f4a2713aSLionel Sambuc case LengthModifier::AsInt3264:
731f4a2713aSLionel Sambuc case LengthModifier::AsInt64:
732f4a2713aSLionel Sambuc switch (CS.getKind()) {
733f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
734f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
735f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
736f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
737f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
738f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
739f4a2713aSLionel Sambuc return Target.getTriple().isOSMSVCRT();
740f4a2713aSLionel Sambuc default:
741f4a2713aSLionel Sambuc return false;
742f4a2713aSLionel Sambuc }
743*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
744*0a6a1f1dSLionel Sambuc switch (CS.getKind()) {
745*0a6a1f1dSLionel Sambuc case ConversionSpecifier::cArg:
746*0a6a1f1dSLionel Sambuc case ConversionSpecifier::CArg:
747*0a6a1f1dSLionel Sambuc case ConversionSpecifier::sArg:
748*0a6a1f1dSLionel Sambuc case ConversionSpecifier::SArg:
749*0a6a1f1dSLionel Sambuc case ConversionSpecifier::ZArg:
750*0a6a1f1dSLionel Sambuc return Target.getTriple().isOSMSVCRT();
751*0a6a1f1dSLionel Sambuc default:
752*0a6a1f1dSLionel Sambuc return false;
753*0a6a1f1dSLionel Sambuc }
754f4a2713aSLionel Sambuc }
755f4a2713aSLionel Sambuc llvm_unreachable("Invalid LengthModifier Kind!");
756f4a2713aSLionel Sambuc }
757f4a2713aSLionel Sambuc
hasStandardLengthModifier() const758f4a2713aSLionel Sambuc bool FormatSpecifier::hasStandardLengthModifier() const {
759f4a2713aSLionel Sambuc switch (LM.getKind()) {
760f4a2713aSLionel Sambuc case LengthModifier::None:
761f4a2713aSLionel Sambuc case LengthModifier::AsChar:
762f4a2713aSLionel Sambuc case LengthModifier::AsShort:
763f4a2713aSLionel Sambuc case LengthModifier::AsLong:
764f4a2713aSLionel Sambuc case LengthModifier::AsLongLong:
765f4a2713aSLionel Sambuc case LengthModifier::AsIntMax:
766f4a2713aSLionel Sambuc case LengthModifier::AsSizeT:
767f4a2713aSLionel Sambuc case LengthModifier::AsPtrDiff:
768f4a2713aSLionel Sambuc case LengthModifier::AsLongDouble:
769f4a2713aSLionel Sambuc return true;
770f4a2713aSLionel Sambuc case LengthModifier::AsAllocate:
771f4a2713aSLionel Sambuc case LengthModifier::AsMAllocate:
772f4a2713aSLionel Sambuc case LengthModifier::AsQuad:
773f4a2713aSLionel Sambuc case LengthModifier::AsInt32:
774f4a2713aSLionel Sambuc case LengthModifier::AsInt3264:
775f4a2713aSLionel Sambuc case LengthModifier::AsInt64:
776*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
777f4a2713aSLionel Sambuc return false;
778f4a2713aSLionel Sambuc }
779f4a2713aSLionel Sambuc llvm_unreachable("Invalid LengthModifier Kind!");
780f4a2713aSLionel Sambuc }
781f4a2713aSLionel Sambuc
hasStandardConversionSpecifier(const LangOptions & LangOpt) const782f4a2713aSLionel Sambuc bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) const {
783f4a2713aSLionel Sambuc switch (CS.getKind()) {
784f4a2713aSLionel Sambuc case ConversionSpecifier::cArg:
785f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
786f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
787f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
788f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
789f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
790f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
791f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
792f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
793f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
794f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
795f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
796f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
797f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
798f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
799f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
800f4a2713aSLionel Sambuc case ConversionSpecifier::pArg:
801f4a2713aSLionel Sambuc case ConversionSpecifier::nArg:
802f4a2713aSLionel Sambuc case ConversionSpecifier::ObjCObjArg:
803f4a2713aSLionel Sambuc case ConversionSpecifier::ScanListArg:
804f4a2713aSLionel Sambuc case ConversionSpecifier::PercentArg:
805f4a2713aSLionel Sambuc return true;
806f4a2713aSLionel Sambuc case ConversionSpecifier::CArg:
807f4a2713aSLionel Sambuc case ConversionSpecifier::SArg:
808f4a2713aSLionel Sambuc return LangOpt.ObjC1 || LangOpt.ObjC2;
809f4a2713aSLionel Sambuc case ConversionSpecifier::InvalidSpecifier:
810f4a2713aSLionel Sambuc case ConversionSpecifier::PrintErrno:
811f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
812f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
813f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
814*0a6a1f1dSLionel Sambuc case ConversionSpecifier::ZArg:
815f4a2713aSLionel Sambuc return false;
816f4a2713aSLionel Sambuc }
817f4a2713aSLionel Sambuc llvm_unreachable("Invalid ConversionSpecifier Kind!");
818f4a2713aSLionel Sambuc }
819f4a2713aSLionel Sambuc
hasStandardLengthConversionCombination() const820f4a2713aSLionel Sambuc bool FormatSpecifier::hasStandardLengthConversionCombination() const {
821f4a2713aSLionel Sambuc if (LM.getKind() == LengthModifier::AsLongDouble) {
822f4a2713aSLionel Sambuc switch(CS.getKind()) {
823f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
824f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
825f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
826f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
827f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
828f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
829f4a2713aSLionel Sambuc return false;
830f4a2713aSLionel Sambuc default:
831f4a2713aSLionel Sambuc return true;
832f4a2713aSLionel Sambuc }
833f4a2713aSLionel Sambuc }
834f4a2713aSLionel Sambuc return true;
835f4a2713aSLionel Sambuc }
836f4a2713aSLionel Sambuc
getCorrectedLengthModifier() const837f4a2713aSLionel Sambuc Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
838f4a2713aSLionel Sambuc if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
839f4a2713aSLionel Sambuc if (LM.getKind() == LengthModifier::AsLongDouble ||
840f4a2713aSLionel Sambuc LM.getKind() == LengthModifier::AsQuad) {
841f4a2713aSLionel Sambuc LengthModifier FixedLM(LM);
842f4a2713aSLionel Sambuc FixedLM.setKind(LengthModifier::AsLongLong);
843f4a2713aSLionel Sambuc return FixedLM;
844f4a2713aSLionel Sambuc }
845f4a2713aSLionel Sambuc }
846f4a2713aSLionel Sambuc
847f4a2713aSLionel Sambuc return None;
848f4a2713aSLionel Sambuc }
849f4a2713aSLionel Sambuc
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)850f4a2713aSLionel Sambuc bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
851f4a2713aSLionel Sambuc LengthModifier &LM) {
852f4a2713aSLionel Sambuc assert(isa<TypedefType>(QT) && "Expected a TypedefType");
853f4a2713aSLionel Sambuc const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
854f4a2713aSLionel Sambuc
855f4a2713aSLionel Sambuc for (;;) {
856f4a2713aSLionel Sambuc const IdentifierInfo *Identifier = Typedef->getIdentifier();
857f4a2713aSLionel Sambuc if (Identifier->getName() == "size_t") {
858f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsSizeT);
859f4a2713aSLionel Sambuc return true;
860f4a2713aSLionel Sambuc } else if (Identifier->getName() == "ssize_t") {
861f4a2713aSLionel Sambuc // Not C99, but common in Unix.
862f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsSizeT);
863f4a2713aSLionel Sambuc return true;
864f4a2713aSLionel Sambuc } else if (Identifier->getName() == "intmax_t") {
865f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsIntMax);
866f4a2713aSLionel Sambuc return true;
867f4a2713aSLionel Sambuc } else if (Identifier->getName() == "uintmax_t") {
868f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsIntMax);
869f4a2713aSLionel Sambuc return true;
870f4a2713aSLionel Sambuc } else if (Identifier->getName() == "ptrdiff_t") {
871f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsPtrDiff);
872f4a2713aSLionel Sambuc return true;
873f4a2713aSLionel Sambuc }
874f4a2713aSLionel Sambuc
875f4a2713aSLionel Sambuc QualType T = Typedef->getUnderlyingType();
876f4a2713aSLionel Sambuc if (!isa<TypedefType>(T))
877f4a2713aSLionel Sambuc break;
878f4a2713aSLionel Sambuc
879f4a2713aSLionel Sambuc Typedef = cast<TypedefType>(T)->getDecl();
880f4a2713aSLionel Sambuc }
881f4a2713aSLionel Sambuc return false;
882f4a2713aSLionel Sambuc }
883