diff options
Diffstat (limited to 'test/SemaObjC/format-strings-objc.m')
-rw-r--r-- | test/SemaObjC/format-strings-objc.m | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m index 987889b..7faa995 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'}} +} + |