void setUsesPositionalArg() { UsesPositionalArg = true; }
void setArgIndex(unsigned i) {
- // assert(CS.consumesDataArgument());
argIndex = i;
}
unsigned getArgIndex() const {
- //assert(CS.consumesDataArgument());
return argIndex;
}
unsigned getPositionalArgIndex() const {
- //assert(CS.consumesDataArgument());
return argIndex + 1;
}
const OptionalAmount &getPrecision() const {
return Precision;
}
+
+ bool consumesDataArgument() const {
+ return CS.consumesDataArgument();
+ }
- /// \brief Returns the builtin type that a data argument
- /// paired with this format specifier should have. This method
- /// will return null if the format specifier does not have
- /// a matching data argument or the matching argument matches
- /// more than one type.
+ /// \brief Returns the builtin type that a data argument
+ /// paired with this format specifier should have. This method
+ /// will return null if the format specifier does not have
+ /// a matching data argument or the matching argument matches
+ /// more than one type.
ArgTypeResult getArgType(ASTContext &Ctx) const;
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
using namespace analyze_printf;
const ConversionSpecifier &CS = FS.getConversionSpecifier();
- if (atFirstArg) {
- atFirstArg = false;
- usesPositionalArgs = FS.usesPositionalArg();
- }
- else if (usesPositionalArgs != FS.usesPositionalArg()) {
- // Cannot mix-and-match positional and non-positional arguments.
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_format_mix_positional_nonpositional_args)
- << getSpecifierRange(startSpecifier, specifierLen);
- return false;
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
}
// First check if the field width, precision, and conversion specifier
const ConversionSpecifier &CS = FS.getConversionSpecifier();
- // FIXME: Handle case where '%' and '*' don't consume an argument.
- // This needs to be done for the printf case as well.
- if (atFirstArg) {
- atFirstArg = false;
- usesPositionalArgs = FS.usesPositionalArg();
- }
- else if (usesPositionalArgs != FS.usesPositionalArg()) {
- // Cannot mix-and-match positional and non-positional arguments.
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_format_mix_positional_nonpositional_args)
- << getSpecifierRange(startSpecifier, specifierLen);
- return false;
+ // Handle case where '%' and '*' don't consume an argument. These shouldn't
+ // be used to decide if we are using positional arguments consistently.
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
}
// Check if the field with is non-zero.
unsigned short s_x;
scanf ("%" "hu" "\n", &s_x); // no-warning
scanf("%y", i); // expected-warning{{invalid conversion specifier 'y'}}
+ scanf("%%"); // no-warning
+ scanf("%%%1$d", i); // no-warning
+ scanf("%1$d%%", i); // no-warning
+ scanf("%d", i, i); // expected-warning{{data argument not used by format string}}
+ scanf("%*d", i); // // expected-warning{{data argument not used by format string}}
+ scanf("%*d", i); // // expected-warning{{data argument not used by format string}}
+ scanf("%*d%1$d", i); // no-warning
}
printf("%1$2.2d", (int) 2); // no-warning
printf("%2$*1$.2d", (int) 2, (int) 3); // no-warning
printf("%2$*8$d", (int) 2, (int) 3); // expected-warning{{specified field width is missing a matching 'int' argument}}
+ printf("%%%1$d", (int) 2); // no-warning
+ printf("%1$d%%", (int) 2); // no-warning
}
// PR 6697 - Handle format strings where the data argument is not adjacent to the format string