aboutsummaryrefslogtreecommitdiff
path: root/test/SemaObjC/format-strings-objc.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaObjC/format-strings-objc.m')
-rw-r--r--test/SemaObjC/format-strings-objc.m57
1 files changed, 53 insertions, 4 deletions
diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m
index 987889bc232f..7faa995002db 100644
--- a/test/SemaObjC/format-strings-objc.m
+++ b/test/SemaObjC/format-strings-objc.m
@@ -31,6 +31,12 @@ extern void *_NSConstantStringClassReference;
typedef const struct __CFString * CFStringRef;
extern void CFStringCreateWithFormat(CFStringRef format, ...) __attribute__((format(CFString, 1, 2)));
+#define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
+
+// This function is used instead of the builtin if -fno-constant-cfstrings.
+// The definition on Mac OS X is NOT annotated with format_arg as of 10.8,
+// but clang will implicitly add the attribute if it's not written.
+extern CFStringRef __CFStringMakeConstantString(const char *);
int printf(const char * restrict, ...) ;
@@ -52,6 +58,7 @@ void rdar_7068334() {
long long test = 500;
printf("%i ",test); // expected-warning{{format specifies type 'int' but the argument has type 'long long'}}
NSLog(@"%i ",test); // expected-warning{{format specifies type 'int' but the argument has type 'long long'}}
+ CFStringCreateWithFormat(CFSTR("%i"),test); // expected-warning{{format specifies type 'int' but the argument has type 'long long'}}
}
// <rdar://problem/7697748>
@@ -72,7 +79,7 @@ extern void MyCFStringCreateWithFormat(CFStringRef format, ...) __attribute__((f
void check_mylog() {
MyNSLog(@"%@"); // expected-warning {{more '%' conversions than data arguments}}
- // FIXME: find a way to test CFString too, but I don't know how to create constant CFString.
+ MyCFStringCreateWithFormat(CFSTR("%@")); // expected-warning {{more '%' conversions than data arguments}}
}
// PR 10275 - format function attribute isn't checked in Objective-C methods
@@ -111,11 +118,20 @@ NSString *test_literal_propagation(void) {
}
// Do not emit warnings when using NSLocalizedString
-extern NSString *GetLocalizedString(NSString *str);
-#define NSLocalizedString(key) GetLocalizedString(key)
+#include "format-strings-system.h"
+
+// Test it inhibits diag only for macros in system headers
+#define MyNSLocalizedString(key) GetLocalizedString(key)
+#define MyNSAssert(fmt, arg) NSLog(fmt, arg, 0, 0)
void check_NSLocalizedString() {
[Foo fooWithFormat:NSLocalizedString(@"format"), @"arg"]; // no-warning
+ [Foo fooWithFormat:MyNSLocalizedString(@"format"), @"arg"]; // expected-warning {{format string is not a string literal}}}
+}
+
+void check_NSAssert() {
+ NSAssert(@"Hello %@", @"World"); // no-warning
+ MyNSAssert(@"Hello %@", @"World"); // expected-warning {{data argument not used by format string}}
}
typedef __WCHAR_TYPE__ wchar_t;
@@ -150,8 +166,12 @@ void test_percent_C() {
}
// Test that %@ works with toll-free bridging (<rdar://problem/10814120>).
-void test_toll_free_bridging(CFStringRef x) {
+void test_toll_free_bridging(CFStringRef x, id y) {
NSLog(@"%@", x); // no-warning
+ CFStringCreateWithFormat(CFSTR("%@"), x); // no-warning
+
+ NSLog(@"%@", y); // no-warning
+ CFStringCreateWithFormat(CFSTR("%@"), y); // no-warning
}
@interface Bar
@@ -186,3 +206,32 @@ int rdar11049844() {
printf("%p", x); // no-warning
}
+void test_nonBuiltinCFStrings() {
+ 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}}
+}
+
+
+// <rdar://problem/11825593>
+void testByValueObjectInFormat(Foo *obj) {
+ printf("%d %d %d", 1L, *obj, 1L); // expected-error {{cannot pass object with interface type 'Foo' by value to variadic function; expected type from format string was 'int'}} expected-warning 2 {{format specifies type 'int' but the argument has type 'long'}}
+
+ [Bar log2:@"%d", *obj]; // expected-error {{cannot pass object with interface type 'Foo' by value to variadic method; expected type from format string was 'int'}}
+}
+