}
}
+// Note that this may return NULL if there was an error parsing or building
+// one of the argument expressions.
const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
return Args[FirstDataArg + i];
}
signed notCoveredArg = CoveredArgs.find_first();
if (notCoveredArg >= 0) {
assert((unsigned)notCoveredArg < NumDataArgs);
- SourceLocation Loc = getDataArg((unsigned) notCoveredArg)->getLocStart();
- if (!S.getSourceManager().isInSystemMacro(Loc)) {
- EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used),
- Loc,
- /*IsStringLocation*/false, getFormatStringRange());
+ if (const Expr *E = getDataArg((unsigned) notCoveredArg)) {
+ SourceLocation Loc = E->getLocStart();
+ if (!S.getSourceManager().isInSystemMacro(Loc)) {
+ EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used),
+ Loc, /*IsStringLocation*/false,
+ getFormatStringRange());
+ }
}
}
}
// doesn't emit a warning for that case.
CoveredArgs.set(argIndex);
const Expr *Arg = getDataArg(argIndex);
+ if (!Arg)
+ return false;
+
QualType T = Arg->getType();
const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context);
if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
return false;
- return checkFormatExpr(FS, startSpecifier, specifierLen,
- getDataArg(argIndex));
+ const Expr *Arg = getDataArg(argIndex);
+ if (!Arg)
+ return true;
+
+ return checkFormatExpr(FS, startSpecifier, specifierLen, Arg);
}
bool
// Check that the argument type matches the format specifier.
const Expr *Ex = getDataArg(argIndex);
+ if (!Ex)
+ return true;
+
const analyze_scanf::ScanfArgTypeResult &ATR = FS.getArgType(S.Context);
if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
ScanfSpecifier fixedFS = FS;
CFStringCreateWithFormat(__CFStringMakeConstantString("%@"), 1); // expected-warning{{format specifies type 'id' but the argument has type 'int'}}
}
+
+// Don't crash on an invalid argument expression.
+// <rdar://problem/11890818>
+@interface NSDictionary : NSObject
+- (id)objectForKeyedSubscript:(id)key;
+@end
+
+void testInvalidFormatArgument(NSDictionary *dict) {
+ NSLog(@"no specifiers", dict[CFSTR("abc")]); // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}}
+ NSLog(@"%@", dict[CFSTR("abc")]); // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}}
+ NSLog(@"%@ %@", dict[CFSTR("abc")]); // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}}
+
+ [Foo fooWithFormat:@"no specifiers", dict[CFSTR("abc")]]; // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}}
+ [Foo fooWithFormat:@"%@", dict[CFSTR("abc")]]; // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}}
+ [Foo fooWithFormat:@"%@ %@", dict[CFSTR("abc")]]; // expected-error{{indexing expression is invalid because subscript type 'CFStringRef' (aka 'const struct __CFString *') is not an integral or objective-C pointer type}} expected-warning{{more '%' conversions than data arguments}}
+}
+