annotate clang/lib/AST/FormatString.cpp @ 209:dd44ba33042e

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