Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -7780,13 +7780,13 @@ // } if (HasVAListArg) { if (const ParmVarDecl *PV = dyn_cast(VD)) { - if (const NamedDecl *ND = dyn_cast(PV->getDeclContext())) { + if (const Decl *D = dyn_cast(PV->getDeclContext())) { int PVIndex = PV->getFunctionScopeIndex() + 1; - for (const auto *PVFormat : ND->specific_attrs()) { - // adjust for implicit parameter - if (const CXXMethodDecl *MD = dyn_cast(ND)) - if (MD->isInstance()) - ++PVIndex; + // adjust for implicit parameter + const CXXMethodDecl *MD = dyn_cast(D); + if (MD && MD->isInstance()) + ++PVIndex; + for (const auto *PVFormat : D->specific_attrs()) { // We also check if the formats are compatible. // We can't pass a 'scanf' string to a 'printf' function. if (PVIndex == PVFormat->getFormatIdx() && Index: clang/test/Sema/format-strings.c =================================================================== --- clang/test/Sema/format-strings.c +++ clang/test/Sema/format-strings.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s +// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s +// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s #include #include @@ -714,3 +714,30 @@ void test_printf_opaque_ptr(void *op) { printf("%s", op); // expected-warning{{format specifies type 'char *' but the argument has type 'void *'}} } + +void test_block() { + void __attribute__((__format__(__printf__, 1, 2))) (^printf_arg1)( + const char *, ...) = + ^(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + }; + + printf_arg1("%s string %i\n", "aaa", 123); + printf_arg1("%s string\n", 123); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}} + + void __attribute__((__format__(__printf__, 2, 3))) (^printf_arg2)( + const char *, const char *, ...) = + ^(const char *not_fmt, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))) { + va_list ap; + va_start(ap, fmt); + vprintf(not_fmt, ap); // expected-warning{{format string is not a string literal}} + va_end(ap); + }; + + printf_arg2("foo", "%s string %i\n", "aaa", 123); + printf_arg2("%s string\n", "foo", "bar"); // expected-warning{{data argument not used by format string}} +}