bool clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, FormatSpecifier &FS, const char *Start, const char *&Beg, const char *E) { const char *I = Beg; const OptionalAmount &Amt = ParseAmount(I, E); if (I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; } if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { // Special case: '%0$', since this is an easy mistake. if (Amt.getConstantAmount() == 0) { H.HandleZeroPosition(Start, I - Start); return true; } FS.setArgIndex(Amt.getConstantAmount() - 1); FS.setUsesPositionalArg(); // Update the caller's pointer if we decided to consume // these characters. Beg = I; return false; } return false; }
bool clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H, FormatSpecifier &FS, const char *&I, const char *E, const LangOptions &LO) { if (!LO.OpenCL) return false; const char *Start = I; if (*I == 'v') { ++I; if (I == E) { H.HandleIncompleteSpecifier(Start, E - Start); return true; } OptionalAmount NumElts = ParseAmount(I, E); if (NumElts.getHowSpecified() != OptionalAmount::Constant) { H.HandleIncompleteSpecifier(Start, E - Start); return true; } FS.setVectorNumElts(NumElts); } return false; }
bool clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, const char *&I, const char *E) { LengthModifier::Kind lmKind = LengthModifier::None; const char *lmPosition = I; switch (*I) { default: return false; case 'h': ++I; lmKind = (I != E && *I == 'h') ? ++I, LengthModifier::AsChar : LengthModifier::AsShort; break; case 'l': ++I; lmKind = (I != E && *I == 'l') ? ++I, LengthModifier::AsLongLong : LengthModifier::AsLong; break; case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; case 'q': lmKind = LengthModifier::AsLongLong; ++I; break; } LengthModifier lm(lmPosition, lmKind); FS.setLengthModifier(lm); return true; }
bool clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &CS, const char *Start, const char *&Beg, const char *E, unsigned *argIndex) { // FIXME: Support negative field widths. if (argIndex) { CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); } else { const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, analyze_format_string::FieldWidthPos); if (Amt.isInvalid()) return true; CS.setFieldWidth(Amt); } return false; }
bool clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, const char *&I, const char *E, const LangOptions &LO, bool IsScanf) { LengthModifier::Kind lmKind = LengthModifier::None; const char *lmPosition = I; switch (*I) { default: return false; case 'h': ++I; lmKind = (I != E && *I == 'h') ? (++I, LengthModifier::AsChar) : LengthModifier::AsShort; break; case 'l': ++I; lmKind = (I != E && *I == 'l') ? (++I, LengthModifier::AsLongLong) : LengthModifier::AsLong; break; case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; case 'q': lmKind = LengthModifier::AsQuad; ++I; break; case 'a': if (IsScanf && !LO.C99 && !LO.CPlusPlus0x) { // For scanf in C90, look at the next character to see if this should // be parsed as the GNU extension 'a' length modifier. If not, this // will be parsed as a conversion specifier. ++I; if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { lmKind = LengthModifier::AsAllocate; break; } --I; } return false; case 'm': if (IsScanf) { lmKind = LengthModifier::AsMAllocate; ++I; break; } return false; } LengthModifier lm(lmPosition, lmKind); FS.setLengthModifier(lm); return true; }
bool clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, const char *&I, const char *E, const LangOptions &LO, bool IsScanf) { LengthModifier::Kind lmKind = LengthModifier::None; const char *lmPosition = I; switch (*I) { default: return false; case 'h': ++I; if (I != E && *I == 'h') { ++I; lmKind = LengthModifier::AsChar; } else { lmKind = LengthModifier::AsShort; } break; case 'l': ++I; if (I != E && *I == 'l') { ++I; lmKind = LengthModifier::AsLongLong; } else { lmKind = LengthModifier::AsLong; } break; case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; case 'q': lmKind = LengthModifier::AsQuad; ++I; break; case 'a': if (IsScanf && !LO.C99 && !LO.CPlusPlus11) { // For scanf in C90, look at the next character to see if this should // be parsed as the GNU extension 'a' length modifier. If not, this // will be parsed as a conversion specifier. ++I; if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { lmKind = LengthModifier::AsAllocate; break; } --I; } return false; case 'm': if (IsScanf) { lmKind = LengthModifier::AsMAllocate; ++I; break; } return false; // printf: AsInt64, AsInt32, AsInt3264 // scanf: AsInt64 case 'I': if (I + 1 != E && I + 2 != E) { if (I[1] == '6' && I[2] == '4') { I += 3; lmKind = LengthModifier::AsInt64; break; } if (IsScanf) return false; if (I[1] == '3' && I[2] == '2') { I += 3; lmKind = LengthModifier::AsInt32; break; } } ++I; lmKind = LengthModifier::AsInt3264; break; case 'w': lmKind = LengthModifier::AsWide; ++I; break; } LengthModifier lm(lmPosition, lmKind); FS.setLengthModifier(lm); return true; }