| 1 | // RUN: %clang_cc1 -verify -Wused-but-marked-unused -Wno-objc-protocol-method-implementation -Wunused -Wunused-parameter -fsyntax-only -Wno-objc-root-class %s |
| 2 | |
| 3 | int printf(const char *, ...); |
| 4 | |
| 5 | @interface Greeter |
| 6 | + (void) hello; |
| 7 | @end |
| 8 | |
| 9 | @implementation Greeter |
| 10 | + (void) hello { printf("Hello, World!\n"); } |
| 11 | @end |
| 12 | |
| 13 | int test1(void) { |
| 14 | [Greeter hello]; |
| 15 | return 0; |
| 16 | } |
| 17 | |
| 18 | @interface NSObject @end |
| 19 | @interface NSString : NSObject |
| 20 | - (int)length; |
| 21 | @end |
| 22 | |
| 23 | void test2() { |
| 24 | @"pointless example call for test purposes".length; // expected-warning {{property access result unused - getters should not be used for side effects}} |
| 25 | } |
| 26 | |
| 27 | @interface foo |
| 28 | - (int)meth: (int)x : (int)y : (int)z ; |
| 29 | @end |
| 30 | |
| 31 | @implementation foo |
| 32 | - (int) meth: (int)x: // expected-warning {{'x' used as the name of the previous parameter rather than as part of the selector}} \ |
| 33 | // expected-note {{introduce a parameter name to make 'x' part of the selector}} \ |
| 34 | // expected-note {{or insert whitespace before ':' to use 'x' as parameter name and have an empty entry in the selector}} |
| 35 | |
| 36 | (int)y: // expected-warning {{unused}} expected-warning {{'y' used as the name of the previous parameter rather than as part of the selector}} \ |
| 37 | // expected-note {{introduce a parameter name to make 'y' part of the selector}} \ |
| 38 | // expected-note {{or insert whitespace before ':' to use 'y' as parameter name and have an empty entry in the selector}} |
| 39 | (int) __attribute__((unused))z { return x; } |
| 40 | @end |
| 41 | |
| 42 | //===------------------------------------------------------------------------=== |
| 43 | // The next test shows how clang accepted attribute((unused)) on ObjC |
| 44 | // instance variables, which GCC does not. |
| 45 | //===------------------------------------------------------------------------=== |
| 46 | |
| 47 | #if __has_feature(attribute_objc_ivar_unused) |
| 48 | #define UNUSED_IVAR __attribute__((unused)) |
| 49 | #else |
| 50 | #error __attribute__((unused)) not supported on ivars |
| 51 | #endif |
| 52 | |
| 53 | @interface TestUnusedIvar { |
| 54 | id y __attribute__((unused)); // no-warning |
| 55 | id x UNUSED_IVAR; // no-warning |
| 56 | } |
| 57 | @end |
| 58 | |
| 59 | // rdar://10777111 |
| 60 | static NSString *x = @"hi"; // expected-warning {{unused variable 'x'}} |
| 61 | |
| 62 | // rdar://12233989 |
| 63 | @interface TestTransitiveUnused |
| 64 | - (void) a __attribute__((unused)); |
| 65 | - (void) b __attribute__((unused)); |
| 66 | @end |
| 67 | |
| 68 | @interface TestTransitiveUnused(CAT) |
| 69 | @end |
| 70 | |
| 71 | @implementation TestTransitiveUnused(CAT) |
| 72 | - (void) b {} |
| 73 | - (void) a { [self b]; } |
| 74 | @end |
| 75 | |
| 76 | // Test that objc_precise_lifetime suppresses |
| 77 | // unused variable warnings. |
| 78 | extern void rdar15596883_foo(void); |
| 79 | void rdar15596883(id x) { |
| 80 | __attribute__((objc_precise_lifetime)) id y = x; // no-warning |
| 81 | rdar15596883_foo(); |
| 82 | } |
| 83 | |
| 84 | @interface PropertyObject : NSObject |
| 85 | @property int length; |
| 86 | @end |
| 87 | |
| 88 | @protocol P |
| 89 | @property int property; |
| 90 | @end |
| 91 | |
| 92 | void test3(PropertyObject *o) |
| 93 | { |
| 94 | [o length]; // No warning. property name used in direct method call. |
| 95 | } |
| 96 | |
| 97 | void test4(id o) |
| 98 | { |
| 99 | [o length]; // No warning. |
| 100 | } |
| 101 | |
| 102 | void test5(id <P> p) |
| 103 | { |
| 104 | [p property]; // No warning. property name used in direct method call. |
| 105 | } |
| 106 | |
| 107 | // rdar://19773512 |
| 108 | @interface Model |
| 109 | @property (nonatomic, retain, setter=setOrCreateGroup:, getter=getOrCreateGroup) id group; |
| 110 | @end |
| 111 | |
| 112 | @implementation Model { |
| 113 | id _group; |
| 114 | } |
| 115 | - (void)method { |
| 116 | [self getOrCreateGroup]; |
| 117 | self.getOrCreateGroup; // expected-warning {{property access result unused - getters should not be used for side effects}} |
| 118 | self.group; // expected-warning {{property access result unused - getters should not be used for side effects}} |
| 119 | self.group = (void*)0; |
| 120 | [self setOrCreateGroup : ((void*)0)]; |
| 121 | |
| 122 | } |
| 123 | - (id)getOrCreateGroup { |
| 124 | if (!_group) { |
| 125 | _group = @"group"; |
| 126 | } |
| 127 | return _group; |
| 128 | } |
| 129 | @end |
| 130 | |
| 131 | |