// more efficient. For example, just map function ids to custom
// handlers.
- // Printf checking.
- if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
+ // Printf and scanf checking.
+ for (specific_attr_iterator<FormatAttr>
+ i = FDecl->specific_attr_begin<FormatAttr>(),
+ e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+ const FormatAttr *Format = *i;
const bool b = Format->getType() == "scanf";
if (b || CheckablePrintfAttr(Format, TheCall)) {
bool HasVAListArg = Format->getFirstArg() == 0;
}
}
- specific_attr_iterator<NonNullAttr>
- i = FDecl->specific_attr_begin<NonNullAttr>(),
- e = FDecl->specific_attr_end<NonNullAttr>();
-
- for (; i != e; ++i)
+ for (specific_attr_iterator<NonNullAttr>
+ i = FDecl->specific_attr_begin<NonNullAttr>(),
+ e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
CheckNonNullArguments(*i, TheCall);
+ }
return false;
}
}
// <rdar://problem/8269537> -Wformat-security says NULL is not a string literal
-void r8269537() {
+void rdar8269537() {
// This is likely to crash in most cases, but -Wformat-nonliteral technically
// doesn't warn in this case.
printf(0); // no-warning
}
+// Handle functions with multiple format attributes.
+extern void rdar8332221_vprintf_scanf(const char *, va_list, const char *, ...)
+ __attribute__((__format__(__printf__, 1, 0)))
+ __attribute__((__format__(__scanf__, 3, 4)));
+
+void rdar8332221(va_list ap, int *x, long *y) {
+ rdar8332221_vprintf_scanf("%", ap, "%d", x); // expected-warning{{incomplete format specifier}}
+}
+