| 1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s |
| 2 | |
| 3 | #include <stdarg.h> |
| 4 | |
| 5 | //===----------------------------------------------------------------------===// |
| 6 | // The following code is reduced using delta-debugging from |
| 7 | // Foundation.h (Mac OS X). |
| 8 | // |
| 9 | // It includes the basic definitions for the test cases below. |
| 10 | // Not directly including Foundation.h directly makes this test case |
| 11 | // both svelte and portable to non-Mac platforms. |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | typedef signed char BOOL; |
| 15 | typedef unsigned int NSUInteger; |
| 16 | typedef struct _NSZone NSZone; |
| 17 | @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; |
| 18 | @protocol NSObject - (BOOL)isEqual:(id)object; |
| 19 | @end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; |
| 20 | @end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end |
| 21 | @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end |
| 22 | @interface NSObject <NSObject> {} @end |
| 23 | extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); |
| 24 | @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> |
| 25 | - (NSUInteger)length; |
| 26 | + (id)stringWithFormat:(NSString *)format, ...; |
| 27 | @end |
| 28 | @interface NSSimpleCString : NSString {} @end |
| 29 | @interface NSConstantString : NSSimpleCString @end |
| 30 | extern void *_NSConstantStringClassReference; |
| 31 | typedef double NSTimeInterval; |
| 32 | @interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; @end |
| 33 | @class NSString, NSDictionary, NSArray; |
| 34 | @interface NSException : NSObject <NSCopying, NSCoding> {} |
| 35 | + (NSException *)exceptionWithName:(NSString *)name reason:(NSString *)reason userInfo:(NSDictionary *)userInfo; |
| 36 | - (void)raise; |
| 37 | @end |
| 38 | @interface NSException (NSExceptionRaisingConveniences) |
| 39 | + (void)raise:(NSString *)name format:(NSString *)format, ...; |
| 40 | + (void)raise:(NSString *)name format:(NSString *)format arguments:(va_list)argList; |
| 41 | @end |
| 42 | |
| 43 | enum {NSPointerFunctionsStrongMemory = (0 << 0), NSPointerFunctionsZeroingWeakMemory = (1 << 0), NSPointerFunctionsOpaqueMemory = (2 << 0), NSPointerFunctionsMallocMemory = (3 << 0), NSPointerFunctionsMachVirtualMemory = (4 << 0), NSPointerFunctionsObjectPersonality = (0 << 8), NSPointerFunctionsOpaquePersonality = (1 << 8), NSPointerFunctionsObjectPointerPersonality = (2 << 8), NSPointerFunctionsCStringPersonality = (3 << 8), NSPointerFunctionsStructPersonality = (4 << 8), NSPointerFunctionsIntegerPersonality = (5 << 8), NSPointerFunctionsCopyIn = (1 << 16), }; |
| 44 | |
| 45 | //===----------------------------------------------------------------------===// |
| 46 | // Test cases. |
| 47 | //===----------------------------------------------------------------------===// |
| 48 | |
| 49 | int f1(int *x, NSString* s) { |
| 50 | |
| 51 | if (x) ++x; |
| 52 | |
| 53 | [NSException raise:@"Blah" format:[NSString stringWithFormat:@"Blah %@", s]]; |
| 54 | |
| 55 | return *x; // no-warning |
| 56 | } |
| 57 | |
| 58 | int f2(int *x, ...) { |
| 59 | |
| 60 | if (x) ++x; |
| 61 | va_list alist; |
| 62 | va_start(alist, x); |
| 63 | |
| 64 | [NSException raise:@"Blah" format:@"Blah %@" arguments:alist]; |
| 65 | |
| 66 | return *x; // no-warning |
| 67 | } |
| 68 | |
| 69 | int f3(int* x) { |
| 70 | |
| 71 | if (x) ++x; |
| 72 | |
| 73 | [[NSException exceptionWithName:@"My Exception" reason:@"Want to test exceptions." userInfo:0] raise]; |
| 74 | |
| 75 | return *x; // no-warning |
| 76 | } |
| 77 | |
| 78 | |
| 79 | @interface CustomException : NSException |
| 80 | @end |
| 81 | |
| 82 | int testCustomException(int *x) { |
| 83 | if (x != 0) return 0; |
| 84 | |
| 85 | [CustomException raise:@"Blah" format:@"abc"]; |
| 86 | |
| 87 | return *x; // no-warning |
| 88 | } |
| 89 | |
| 90 | // Test that __attribute__((analyzer_noreturn)) has the intended |
| 91 | // effect on Objective-C methods. |
| 92 | |
| 93 | @interface Radar11634353 |
| 94 | + (void) doesNotReturn __attribute__((analyzer_noreturn)); |
| 95 | - (void) alsoDoesNotReturn __attribute__((analyzer_noreturn)); |
| 96 | @end |
| 97 | |
| 98 | void test_rdar11634353() { |
| 99 | [Radar11634353 doesNotReturn]; |
| 100 | int *p = 0; |
| 101 | *p = 0xDEADBEEF; // no-warning |
| 102 | } |
| 103 | |
| 104 | void test_rdar11634352_instance(Radar11634353 *o) { |
| 105 | [o alsoDoesNotReturn]; |
| 106 | int *p = 0; |
| 107 | *p = 0xDEADBEEF; // no-warning |
| 108 | } |
| 109 | |
| 110 | void test_rdar11634353_positive() { |
| 111 | int *p = 0; |
| 112 | *p = 0xDEADBEEF; // expected-warning {{null pointer}} |
| 113 | } |
| 114 | |
| 115 | // Test analyzer_noreturn on category methods. |
| 116 | @interface NSException (OBExtensions) |
| 117 | + (void)raise:(NSString *)name reason:(NSString *)reason __attribute__((analyzer_noreturn)); |
| 118 | @end |
| 119 | |
| 120 | void PR11959(int *p) { |
| 121 | if (!p) |
| 122 | [NSException raise:@"Bad Pointer" reason:@"Who knows?"]; |
| 123 | *p = 0xDEADBEEF; // no-warning |
| 124 | } |
| 125 | |
| 126 | // Test that hard-coded Microsoft _wassert name is recognized as a noreturn |
| 127 | #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(#_Expression, __FILE__, __LINE__), 0) ) |
| 128 | extern void _wassert(const char * _Message, const char *_File, unsigned _Line); |
| 129 | void test_wassert() { |
| 130 | assert(0); |
| 131 | int *p = 0; |
| 132 | *p = 0xDEADBEEF; // no-warning |
| 133 | } |
| 134 | #undef assert |
| 135 | |
| 136 | // Test that hard-coded Android __assert2 name is recognized as a noreturn |
| 137 | #define assert(_Expression) ((_Expression) ? (void)0 : __assert2(0, 0, 0, 0)); |
| 138 | extern void __assert2(const char *, int, const char *, const char *); |
| 139 | extern void _wassert(const char * _Message, const char *_File, unsigned _Line); |
| 140 | void test___assert2() { |
| 141 | assert(0); |
| 142 | int *p = 0; |
| 143 | *p = 0xDEADBEEF; // no-warning |
| 144 | } |
| 145 | #undef assert |
| 146 | |