// RUN: %clang_analyze_cc1 -fblocks \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=osx.cocoa.MissingSuperCall \ // RUN: -analyzer-checker=osx.cocoa.NSError \ // RUN: -analyzer-checker=osx.ObjCProperty \ // RUN: -analyzer-checker=osx.cocoa.RetainCount \ // RUN: -analyzer-checker=unix.Malloc \ // RUN: -analyzer-checker=alpha.core.CastToStruct \ // RUN: -Wno-unused-value -Wno-objc-root-class -verify %s #define SUPPRESS __attribute__((suppress)) #define SUPPRESS_SPECIFIC(...) __attribute__((suppress(__VA_ARGS__))) @protocol NSObject - (id)retain; - (oneway void)release; @end @interface NSObject { } - (id)init; + (id)alloc; @end typedef int NSInteger; typedef char BOOL; typedef struct _NSZone NSZone; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end @class NSDictionary; @interface NSError : NSObject { } + (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict; @end @interface NSMutableString : NSObject @end typedef __typeof__(sizeof(int)) size_t; void *malloc(size_t); void free(void *); void dereference_1() { int *x = 0; *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } void dereference_suppression_1() { int *x = 0; SUPPRESS { *x; } // no-warning } void dereference_2() { int *x = 0; if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } } void dereference_suppression_2() { int *x = 0; SUPPRESS if (*x) { // no-warning } } void dereference_suppression_2a() { int *x = 0; // FIXME: Implement suppressing individual checkers. SUPPRESS_SPECIFIC("core.NullDereference") if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } } void dereference_suppression_2b() { int *x = 0; // This is not a MallocChecker issue so it shouldn't be suppressed. (Though the attribute // doesn't really understand any of those arguments yet.) SUPPRESS_SPECIFIC("unix.Malloc") if (*x) { // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } } void dereference_3(int cond) { int *x = 0; if (cond) { (*x)++; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } } void dereference_suppression_3(int cond) { int *x = 0; SUPPRESS if (cond) { (*x)++; // no-warning } } void dereference_4() { int *x = 0; int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} } void dereference_suppression_4() { int *x = 0; SUPPRESS int y = *x; // no-warning } void dereference_5() { int *x = 0; int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} int z = *x; // no-warning (duplicate) } void dereference_suppression_5_1() { int *x = 0; SUPPRESS int y = *x; // no-warning int z = *x; // no-warning (duplicate) } void dereference_suppression_5_2() { int *x = 0; int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} SUPPRESS int z = *x; // no-warning } void do_deref(int *y) { *y = 1; // expected-warning{{Dereference of null pointer (loaded from variable 'y')}} } void dereference_interprocedural() { int *x = 0; do_deref(x); } void do_deref_suppressed(int *y) { SUPPRESS *y = 1; // no-warning } void dereference_interprocedural_suppressed() { int *x = 0; do_deref_suppressed(x); } int malloc_leak_1() { int *x = (int *)malloc(sizeof(int)); *x = 42; return *x; // expected-warning{{Potential leak of memory pointed to by 'x'}} } int malloc_leak_suppression_1_1() { SUPPRESS int *x = (int *)malloc(sizeof(int)); *x = 42; return *x; } int malloc_leak_suppression_1_2() { int *x = (int *)malloc(sizeof(int)); *x = 42; SUPPRESS return *x; } void malloc_leak_2() { int *x = (int *)malloc(sizeof(int)); *x = 42; } // expected-warning{{Potential leak of memory pointed to by 'x'}} void malloc_leak_suppression_2_1() { SUPPRESS int *x = (int *)malloc(sizeof(int)); *x = 42; } // TODO: reassess when we decide what to do with declaration annotations void malloc_leak_suppression_2_2() /* SUPPRESS */ { int *x = (int *)malloc(sizeof(int)); *x = 42; } // expected-warning{{Potential leak of memory pointed to by 'x'}} // TODO: reassess when we decide what to do with declaration annotations /* SUPPRESS */ void malloc_leak_suppression_2_3() { int *x = (int *)malloc(sizeof(int)); *x = 42; } // expected-warning{{Potential leak of memory pointed to by 'x'}} void malloc_leak_suppression_2_4(int cond) { int *x = (int *)malloc(sizeof(int)); *x = 42; SUPPRESS; // FIXME: The warning should be suppressed but dead symbol elimination // happens too late. } // expected-warning{{Potential leak of memory pointed to by 'x'}} void retain_release_leak_1() { [[NSMutableString alloc] init]; // expected-warning{{Potential leak of an object of type 'NSMutableString *'}} } void retain_release_leak_suppression_1() { SUPPRESS { [[NSMutableString alloc] init]; } } void retain_release_leak_2(int cond) { id obj = [[NSMutableString alloc] init]; // expected-warning{{Potential leak of an object stored into 'obj'}} if (cond) { [obj release]; } } void retain_release_leak__suppression_2(int cond) { SUPPRESS id obj = [[NSMutableString alloc] init]; if (cond) { [obj release]; } } @interface UIResponder : NSObject { } - (char)resignFirstResponder; @end @interface Test : UIResponder { } @property(copy) NSMutableString *mutableStr; // expected-warning@-1 {{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} @end @implementation Test - (BOOL)resignFirstResponder { return 0; } // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'Test' is missing a [super resignFirstResponder] call}} - (void)methodWhichMayFail:(NSError **)error { // expected-warning@-1 {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred}} } @end @interface TestSuppress : UIResponder { } // TODO: reassess when we decide what to do with declaration annotations @property(copy) /* SUPPRESS */ NSMutableString *mutableStr; // expected-warning@-1 {{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} @end @implementation TestSuppress // TODO: reassess when we decide what to do with declaration annotations - (BOOL)resignFirstResponder /* SUPPRESS */ { return 0; } // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'TestSuppress' is missing a [super resignFirstResponder] call}} // TODO: reassess when we decide what to do with declaration annotations - (void)methodWhichMayFail:(NSError **)error /* SUPPRESS */ { // expected-warning@-1 {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred}} } @end struct AB { int A, B; }; struct ABC { int A, B, C; }; void ast_checker_1() { struct AB Ab; struct ABC *Abc; Abc = (struct ABC *)&Ab; // expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} } void ast_checker_suppress_1() { struct AB Ab; struct ABC *Abc; SUPPRESS { Abc = (struct ABC *)&Ab; } }