aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaChecking.cpp5
-rw-r--r--test/SemaCXX/format-strings.cpp60
-rw-r--r--test/SemaObjCXX/format-strings.mm81
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}}
+ }
+}
+