diff options
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/format-strings.cpp | 60 | ||||
-rw-r--r-- | test/SemaObjCXX/format-strings.mm | 81 |
3 files changed, 142 insertions, 4 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index ebb6cd1065..7498d34892 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -495,9 +495,8 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args, SourceLocation Loc, SourceRange Range, VariadicCallType CallType) { - // FIXME: This mechanism should be abstracted to be less fragile and - // more efficient. For example, just map function ids to custom - // handlers. + if (CurContext->isDependentContext()) + return; // Printf and scanf checking. bool HandledFormatString = false; diff --git a/test/SemaCXX/format-strings.cpp b/test/SemaCXX/format-strings.cpp index 6b0df29353..299aa81bb1 100644 --- a/test/SemaCXX/format-strings.cpp +++ b/test/SemaCXX/format-strings.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic -fblocks %s #include <stdarg.h> @@ -75,3 +75,61 @@ int Foo::printf2(const char *fmt, ...) { return 0; } + + +namespace Templates { + template<typename T> + void my_uninstantiated_print(const T &arg) { + printf("%d", arg); // no-warning + } + + template<typename T> + void my_print(const T &arg) { + printf("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + + void use_my_print() { + my_print("abc"); // expected-note {{requested here}} + } + + + template<typename T> + class UninstantiatedPrinter { + public: + static void print(const T &arg) { + printf("%d", arg); // no-warning + } + }; + + template<typename T> + class Printer { + void format(const char *fmt, ...) __attribute__((format(printf,2,3))); + public: + + void print(const T &arg) { + format("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + }; + + void use_class(Printer<const char *> &p) { + p.print("abc"); // expected-note {{requested here}} + } + + + extern void (^block_print)(const char * format, ...) __attribute__((format(printf, 1, 2))); + + template<typename T> + void uninstantiated_call_block_print(const T &arg) { + block_print("%d", arg); // no-warning + } + + template<typename T> + void call_block_print(const T &arg) { + block_print("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + + void use_block_print() { + call_block_print("abc"); // expected-note {{requested here}} + } +} + diff --git a/test/SemaObjCXX/format-strings.mm b/test/SemaObjCXX/format-strings.mm new file mode 100644 index 0000000000..2fb92e2756 --- /dev/null +++ b/test/SemaObjCXX/format-strings.mm @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s + +#include <stdarg.h> + +extern "C" { +extern int scanf(const char *restrict, ...); +extern int printf(const char *restrict, ...); +extern int vprintf(const char *restrict, va_list); +} + +@class NSString; + +@interface Format ++ (void)print:(NSString *)format, ... __attribute__((format(NSString, 1, 2))); +@end + + +namespace Templates { + template<typename T> + void my_uninstantiated_print(const T &arg) { + [Format print:@"%d", arg]; + } + + template<typename T> + void my_print(const T &arg) { + [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + + void use_my_print() { + my_print("abc"); // expected-note {{requested here}} + } + + + template<typename T> + class UninstantiatedPrinter { + public: + static void print(const T &arg) { + [Format print:@"%d", arg]; // no-warning + } + }; + + template<typename T> + class Printer { + public: + void print(const T &arg) { + [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + }; + + void use_class(Printer<const char *> &p) { + p.print("abc"); // expected-note {{requested here}} + } + + + template<typename T> + class UninstantiatedWrapper { + public: + class Printer { + public: + void print(const T &arg) { + [Format print:@"%d", arg]; // no-warning + } + }; + }; + + template<typename T> + class Wrapper { + public: + class Printer { + public: + void print(const T &arg) { + [Format print:@"%d", arg]; // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}} + } + }; + }; + + void use_class(Wrapper<const char *>::Printer &p) { + p.print("abc"); // expected-note {{requested here}} + } +} + |