1 // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Shared details for processing format strings of printf and scanf
13 //===----------------------------------------------------------------------===//
15 #include "FormatStringParsing.h"
17 using clang::analyze_format_string::ArgTypeResult
;
18 using clang::analyze_format_string::FormatStringHandler
;
19 using clang::analyze_format_string::FormatSpecifier
;
20 using clang::analyze_format_string::LengthModifier
;
21 using clang::analyze_format_string::OptionalAmount
;
22 using clang::analyze_format_string::PositionContext
;
23 using clang::analyze_format_string::ConversionSpecifier
;
24 using namespace clang
;
26 // Key function to FormatStringHandler.
27 FormatStringHandler::~FormatStringHandler() {}
29 //===----------------------------------------------------------------------===//
30 // Functions for parsing format strings components in both printf and
31 // scanf format strings.
32 //===----------------------------------------------------------------------===//
35 clang::analyze_format_string::ParseAmount(const char *&Beg
, const char *E
) {
37 UpdateOnReturn
<const char*> UpdateBeg(Beg
, I
);
39 unsigned accumulator
= 0;
40 bool hasDigits
= false;
42 for ( ; I
!= E
; ++I
) {
44 if (c
>= '0' && c
<= '9') {
46 accumulator
= (accumulator
* 10) + (c
- '0');
51 return OptionalAmount(OptionalAmount::Constant
, accumulator
, Beg
, I
- Beg
,
57 return OptionalAmount();
61 clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg
,
66 return OptionalAmount(OptionalAmount::Arg
, argIndex
++, Beg
, 0, false);
69 return ParseAmount(Beg
, E
);
73 clang::analyze_format_string::ParsePositionAmount(FormatStringHandler
&H
,
79 const char *I
= Beg
+ 1;
80 const OptionalAmount
&Amt
= ParseAmount(I
, E
);
82 if (Amt
.getHowSpecified() == OptionalAmount::NotSpecified
) {
83 H
.HandleInvalidPosition(Beg
, I
- Beg
, p
);
84 return OptionalAmount(false);
88 // No more characters left?
89 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
90 return OptionalAmount(false);
93 assert(Amt
.getHowSpecified() == OptionalAmount::Constant
);
96 // Handle positional arguments
98 // Special case: '*0$', since this is an easy mistake.
99 if (Amt
.getConstantAmount() == 0) {
100 H
.HandleZeroPosition(Beg
, I
- Beg
+ 1);
101 return OptionalAmount(false);
104 const char *Tmp
= Beg
;
107 return OptionalAmount(OptionalAmount::Arg
, Amt
.getConstantAmount() - 1,
111 H
.HandleInvalidPosition(Beg
, I
- Beg
, p
);
112 return OptionalAmount(false);
115 return ParseAmount(Beg
, E
);
120 clang::analyze_format_string::ParseFieldWidth(FormatStringHandler
&H
,
123 const char *&Beg
, const char *E
,
124 unsigned *argIndex
) {
125 // FIXME: Support negative field widths.
127 CS
.setFieldWidth(ParseNonPositionAmount(Beg
, E
, *argIndex
));
130 const OptionalAmount Amt
=
131 ParsePositionAmount(H
, Start
, Beg
, E
,
132 analyze_format_string::FieldWidthPos
);
136 CS
.setFieldWidth(Amt
);
142 clang::analyze_format_string::ParseArgPosition(FormatStringHandler
&H
,
149 const OptionalAmount
&Amt
= ParseAmount(I
, E
);
152 // No more characters left?
153 H
.HandleIncompleteSpecifier(Start
, E
- Start
);
157 if (Amt
.getHowSpecified() == OptionalAmount::Constant
&& *(I
++) == '$') {
158 // Special case: '%0$', since this is an easy mistake.
159 if (Amt
.getConstantAmount() == 0) {
160 H
.HandleZeroPosition(Start
, I
- Start
);
164 FS
.setArgIndex(Amt
.getConstantAmount() - 1);
165 FS
.setUsesPositionalArg();
166 // Update the caller's pointer if we decided to consume
176 clang::analyze_format_string::ParseLengthModifier(FormatSpecifier
&FS
,
179 LengthModifier::Kind lmKind
= LengthModifier::None
;
180 const char *lmPosition
= I
;
186 lmKind
= (I
!= E
&& *I
== 'h') ?
187 ++I
, LengthModifier::AsChar
: LengthModifier::AsShort
;
191 lmKind
= (I
!= E
&& *I
== 'l') ?
192 ++I
, LengthModifier::AsLongLong
: LengthModifier::AsLong
;
194 case 'j': lmKind
= LengthModifier::AsIntMax
; ++I
; break;
195 case 'z': lmKind
= LengthModifier::AsSizeT
; ++I
; break;
196 case 't': lmKind
= LengthModifier::AsPtrDiff
; ++I
; break;
197 case 'L': lmKind
= LengthModifier::AsLongDouble
; ++I
; break;
198 case 'q': lmKind
= LengthModifier::AsLongLong
; ++I
; break;
200 LengthModifier
lm(lmPosition
, lmKind
);
201 FS
.setLengthModifier(lm
);
205 //===----------------------------------------------------------------------===//
206 // Methods on ArgTypeResult.
207 //===----------------------------------------------------------------------===//
209 bool ArgTypeResult::matchesType(ASTContext
&C
, QualType argTy
) const {
212 assert(false && "ArgTypeResult must be valid");
219 argTy
= C
.getCanonicalType(argTy
).getUnqualifiedType();
222 if (const BuiltinType
*BT
= argTy
->getAs
<BuiltinType
>())
223 switch (BT
->getKind()) {
226 case BuiltinType::Char_S
:
227 case BuiltinType::SChar
:
228 return T
== C
.UnsignedCharTy
;
229 case BuiltinType::Char_U
:
230 case BuiltinType::UChar
:
231 return T
== C
.SignedCharTy
;
232 case BuiltinType::Short
:
233 return T
== C
.UnsignedShortTy
;
234 case BuiltinType::UShort
:
235 return T
== C
.ShortTy
;
236 case BuiltinType::Int
:
237 return T
== C
.UnsignedIntTy
;
238 case BuiltinType::UInt
:
240 case BuiltinType::Long
:
241 return T
== C
.UnsignedLongTy
;
242 case BuiltinType::ULong
:
243 return T
== C
.LongTy
;
244 case BuiltinType::LongLong
:
245 return T
== C
.UnsignedLongLongTy
;
246 case BuiltinType::ULongLong
:
247 return T
== C
.LongLongTy
;
253 const PointerType
*PT
= argTy
->getAs
<PointerType
>();
256 QualType pointeeTy
= PT
->getPointeeType();
257 if (const BuiltinType
*BT
= pointeeTy
->getAs
<BuiltinType
>())
258 switch (BT
->getKind()) {
259 case BuiltinType::Void
:
260 case BuiltinType::Char_U
:
261 case BuiltinType::UChar
:
262 case BuiltinType::Char_S
:
263 case BuiltinType::SChar
:
273 const PointerType
*PT
= argTy
->getAs
<PointerType
>();
277 C
.getCanonicalType(PT
->getPointeeType()).getUnqualifiedType();
278 return pointeeTy
== C
.getWCharType();
282 // Instead of doing a lookup for the definition of 'wint_t' (which
283 // is defined by the system headers) instead see if wchar_t and
284 // the argument type promote to the same type.
285 QualType PromoWChar
=
286 C
.getWCharType()->isPromotableIntegerType()
287 ? C
.getPromotedIntegerType(C
.getWCharType()) : C
.getWCharType();
289 argTy
->isPromotableIntegerType()
290 ? C
.getPromotedIntegerType(argTy
) : argTy
;
292 PromoWChar
= C
.getCanonicalType(PromoWChar
).getUnqualifiedType();
293 PromoArg
= C
.getCanonicalType(PromoArg
).getUnqualifiedType();
295 return PromoWChar
== PromoArg
;
299 return argTy
->isPointerType() || argTy
->isObjCObjectPointerType() ||
300 argTy
->isNullPtrType();
303 return argTy
->getAs
<ObjCObjectPointerType
>() != NULL
;
306 // FIXME: Should be unreachable, but Clang is currently emitting
311 QualType
ArgTypeResult::getRepresentativeType(ASTContext
&C
) const {
314 assert(false && "No representative type for Invalid ArgTypeResult");
321 return C
.getPointerType(C
.CharTy
);
323 return C
.getPointerType(C
.getWCharType());
325 return C
.ObjCBuiltinIdTy
;
329 QualType WC
= C
.getWCharType();
330 return WC
->isPromotableIntegerType() ? C
.getPromotedIntegerType(WC
) : WC
;
334 // FIXME: Should be unreachable, but Clang is currently emitting
339 //===----------------------------------------------------------------------===//
340 // Methods on OptionalAmount.
341 //===----------------------------------------------------------------------===//
344 analyze_format_string::OptionalAmount::getArgType(ASTContext
&Ctx
) const {
348 //===----------------------------------------------------------------------===//
349 // Methods on LengthModifier.
350 //===----------------------------------------------------------------------===//
353 analyze_format_string::LengthModifier::toString() const {
359 case AsLong
: // or AsWideChar
377 //===----------------------------------------------------------------------===//
378 // Methods on OptionalAmount.
379 //===----------------------------------------------------------------------===//
381 void OptionalAmount::toString(llvm::raw_ostream
&os
) const {
389 if (usesPositionalArg())
390 os
<< "*" << getPositionalArgIndex() << "$";
402 //===----------------------------------------------------------------------===//
403 // Methods on ConversionSpecifier.
404 //===----------------------------------------------------------------------===//
406 bool FormatSpecifier::hasValidLengthModifier() const {
407 switch (LM
.getKind()) {
408 case LengthModifier::None
:
411 // Handle most integer flags
412 case LengthModifier::AsChar
:
413 case LengthModifier::AsShort
:
414 case LengthModifier::AsLongLong
:
415 case LengthModifier::AsIntMax
:
416 case LengthModifier::AsSizeT
:
417 case LengthModifier::AsPtrDiff
:
418 switch (CS
.getKind()) {
419 case ConversionSpecifier::dArg
:
420 case ConversionSpecifier::iArg
:
421 case ConversionSpecifier::oArg
:
422 case ConversionSpecifier::uArg
:
423 case ConversionSpecifier::xArg
:
424 case ConversionSpecifier::XArg
:
425 case ConversionSpecifier::nArg
:
432 case LengthModifier::AsLong
:
433 switch (CS
.getKind()) {
434 case ConversionSpecifier::dArg
:
435 case ConversionSpecifier::iArg
:
436 case ConversionSpecifier::oArg
:
437 case ConversionSpecifier::uArg
:
438 case ConversionSpecifier::xArg
:
439 case ConversionSpecifier::XArg
:
440 case ConversionSpecifier::aArg
:
441 case ConversionSpecifier::AArg
:
442 case ConversionSpecifier::fArg
:
443 case ConversionSpecifier::FArg
:
444 case ConversionSpecifier::eArg
:
445 case ConversionSpecifier::EArg
:
446 case ConversionSpecifier::gArg
:
447 case ConversionSpecifier::GArg
:
448 case ConversionSpecifier::nArg
:
449 case ConversionSpecifier::cArg
:
450 case ConversionSpecifier::sArg
:
456 case LengthModifier::AsLongDouble
:
457 switch (CS
.getKind()) {
458 case ConversionSpecifier::aArg
:
459 case ConversionSpecifier::AArg
:
460 case ConversionSpecifier::fArg
:
461 case ConversionSpecifier::FArg
:
462 case ConversionSpecifier::eArg
:
463 case ConversionSpecifier::EArg
:
464 case ConversionSpecifier::gArg
:
465 case ConversionSpecifier::GArg
: