llvm-project/clang/test/Analysis/edges-new.mm

593 lines
10 KiB
XML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-output=plist -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t -w %s
// RUN: %normalize_plist <%t | diff -ub %S/Inputs/expected-plists/edges-new.mm.plist -
//===----------------------------------------------------------------------===//
// Forward declarations (from headers).
//===----------------------------------------------------------------------===//
typedef const struct __CFNumber * CFNumberRef;
typedef const struct __CFAllocator * CFAllocatorRef;
extern const CFAllocatorRef kCFAllocatorDefault;
typedef signed long CFIndex;
enum {
kCFNumberSInt8Type = 1,
kCFNumberSInt16Type = 2,
kCFNumberSInt32Type = 3,
kCFNumberSInt64Type = 4,
kCFNumberFloat32Type = 5,
kCFNumberFloat64Type = 6,
kCFNumberCharType = 7,
kCFNumberShortType = 8,
kCFNumberIntType = 9,
kCFNumberLongType = 10,
kCFNumberLongLongType = 11,
kCFNumberFloatType = 12,
kCFNumberDoubleType = 13,
kCFNumberCFIndexType = 14,
kCFNumberNSIntegerType = 15,
kCFNumberCGFloatType = 16,
kCFNumberMaxType = 16
};
typedef CFIndex CFNumberType;
CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
#define nil ((id)0)
__attribute__((objc_root_class))
@interface NSObject
+ (instancetype) alloc;
- (instancetype) init;
- (instancetype)retain;
- (void)release;
@end
@interface NSArray : NSObject
@end
//===----------------------------------------------------------------------===//
// Basic tracking of null and tests for null.
//===----------------------------------------------------------------------===//
void test_null_init(void) {
int *p = 0;
*p = 0xDEADBEEF;
}
void test_null_assign(void) {
int *p;
p = 0;
*p = 0xDEADBEEF;
}
void test_null_assign_transitive(void) {
int *p;
p = 0;
int *q = p;
*q = 0xDEADBEEF;
}
void test_null_cond(int *p) {
if (!p) {
*p = 0xDEADBEEF;
}
}
void test_null_cond_transitive(int *q) {
if (!q) {
int *p = q;
*p = 0xDEADBEEF;
}
}
void test_null_field(void) {
struct s { int *p; } x;
x.p = 0;
*(x.p) = 0xDEADBEEF;
}
void test_assumptions(int a, int b)
{
if (a == 0) {
return;
}
if (b != 0) {
return;
}
int *p = 0;
*p = 0xDEADBEEF;
}
int *bar_cond_assign();
int test_cond_assign() {
int *p;
if ((p = bar_cond_assign()))
return 1;
return *p;
}
//===----------------------------------------------------------------------===//
// Diagnostics for leaks and "noreturn" paths.
//===----------------------------------------------------------------------===//
// <rdar://problem/8331641> leak reports should not show paths that end with exit() (but ones that don't end with exit())
void stop() __attribute__((noreturn));
void rdar8331641(int x) {
signed z = 1;
CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z); // expected-warning{{leak}}
if (x)
stop();
(void) value;
}
//===----------------------------------------------------------------------===//
// Test loops and control-flow.
//===----------------------------------------------------------------------===//
void test_objc_fast_enumeration(NSArray *x) {
id obj;
for (obj in x)
*(volatile int *)0 = 0;
}
void test_objc_fast_enumeration_2(id arr) {
int x;
for (id obj in arr) {
x = 1;
}
x += 1;
}
// Test that loops are documented in the path.
void rdar12280665() {
for (unsigned i = 0; i < 2; ++i) {
if (i == 1) {
int *p = 0;
*p = 0xDEADBEEF; // expected-warning {{dereference}}
}
}
}
// Test for a "loop executed 0 times" diagnostic.
int *radar12322528_bar();
void radar12322528_for(int x) {
int z;
int *p = 0;
for (unsigned i = 0; i < x; ++i) {
p = radar12322528_bar();
}
*p = 0xDEADBEEF;
}
void radar12322528_while(int x) {
int *p = 0;
unsigned i = 0;
for ( ; i < x ; ) {
++i;
p = radar12322528_bar();
}
*p = 0xDEADBEEF;
}
void radar12322528_foo_2() {
int *p = 0;
for (unsigned i = 0; i < 2; ++i) {
if (i == 0)
continue;
if (i == 1) {
break;
}
}
*p = 0xDEADBEEF;
}
void test_loop_diagnostics() {
int *p = 0;
for (int i = 0; i < 2; ++i) { p = 0; }
*p = 1;
}
void test_loop_diagnostics_2() {
int *p = 0;
for (int i = 0; i < 2; ) {
++i;
p = 0;
}
*p = 1;
}
void test_loop_diagnostics_3() {
int z;
int y;
int k;
int *p = 0;
int i = 0;
while (i < 2) {
++i;
p = 0;
}
* p = 1;
}
void test_do_while() {
unsigned i = 0;
int *p;
do {
++i;
p = 0;
} while (i< 2);
*p = 0xDEADBEEF;
}
void test_logical_and() {
int *p = 0;
if (1 && 2) {
*p = 0xDEADBEEF;
}
}
void test_logical_or() {
int *p = 0;
if (0 || 2) {
*p = 0xDEADBEEF;
}
}
void test_logical_or_call() {
extern int call(int);
int *p = 0;
if (call(0 || 2)) {
*p = 0xDEADBEEF;
}
}
void test_nested_logicals(int coin) {
int *p = 0;
if ((0 || 0) || coin) {
*p = 0xDEADBEEF;
}
if (0 || (0 || !coin)) {
*p = 0xDEADBEEF;
}
}
void test_deeply_nested_logicals() {
extern int call(int);
int *p = 0;
if ((0 || (5 && 0)) ? 0 : ((0 || 4) ? call(1 && 5) : 0)) {
*p = 0xDEADBEEF;
}
}
void test_ternary(int x, int *y) {
int z = x ? 0 : 1;
int *p = z ? y : 0;
*p = 0xDEADBEEF;
}
void testUseless(int *y) {
if (y) {
}
if (y) {
}
int *p = 0;
*p = 0xDEADBEEF;
}
//===----------------------------------------------------------------------===//
// Interprocedural tests.
//===----------------------------------------------------------------------===//
@interface IPA_Foo
- (int *) returnsPointer;
@end
int testFoo(IPA_Foo *x) {
if (x)
return 1;
return *[x returnsPointer];
}
@interface IPA_X : NSObject
- (int *)getPointer;
@end
void test1_IPA_X() {
IPA_X *x = nil;
*[x getPointer] = 1; // here
}
@interface IPA_Y : NSObject
- (IPA_Y *)opaque;
- (IPA_X *)getX;
@end
@implementation IPA_Y
- (IPA_X *)getX {
return nil;
}
@end
void test_IPA_Y(IPA_Y *y) {
if (y)
return;
IPA_X *x = [[y opaque] getX]; // here
*[x getPointer] = 1;
}
// From diagnostics/report-issues-within-main-file.cpp:
void causeDivByZeroInMain(int in) {
int m = 0;
m = in/m;
m++;
}
void mainPlusMain() {
int i = 0;
i++;
causeDivByZeroInMain(i);
i++;
}
// From inlining/path-notes.c:
int *getZero() {
int *p = 0;
return p;
}
void usePointer(int *p) {
*p = 1;
}
void testUseOfNullPointer() {
// Test the case where an argument expression is itself a call.
usePointer(getZero());
}
//===----------------------------------------------------------------------===//
// Misc. tests.
//===----------------------------------------------------------------------===//
// Test for tracking null state of ivars.
@interface RDar12114812 : NSObject { char *p; }
@end
@implementation RDar12114812
- (void)test {
p = 0;
*p = 1;
}
@end
// Test diagnostics for initialization of structs.
void RDar13295437_f(void *i) __attribute__((__nonnull__));
struct RDar13295437_S { int *i; };
int RDar13295437() {
struct RDar13295437_S s = {0};
struct RDar13295437_S *sp = &s;
RDar13295437_f(sp->i);
return 0;
}
void testCast(int coin) {
if (coin) {
(void)(1+2);
(void)(2+3);
(void)(3+4);
*(volatile int *)0 = 1;
}
}
// The following previously crashed when generating extensive diagnostics.
// <rdar://problem/10797980>
@interface RDar10797980_help
@property (readonly) int x;
@end
@interface RDar10797980 : NSObject {
RDar10797980_help *y;
}
- (void) test;
@end
@implementation RDar10797980
- (void) test {
if (y.x == 1) {
int *p = 0;
*p = 0xDEADBEEF; // expected-warning {{deference}}
}
}
// The original source for the above Radar contains another problem:
// if the end-of-path node is an implicit statement, it may not have a valid
// source location. <rdar://problem/12446776>
- (void)test2 {
if (bar_cond_assign()) {
id foo = [[RDar10797980 alloc] init]; // leak
}
(void)y; // first statement after the 'if' is an implicit 'self' DeclRefExpr
}
@end
void variousLoops(id input) {
extern int a();
extern int b();
extern int c();
extern int work();
while (a()) {
work();
work();
work();
*(volatile int *)0 = 1;
}
int first = 1;
do {
work();
work();
work();
if (!first)
*(volatile int *)0 = 1;
first = 0;
} while (a());
for (int i = 0; i != b(); ++i) {
work();
*(volatile int *)0 = 1;
}
for (id x in input) {
work();
work();
work();
(void)x;
*(volatile int *)0 = 1;
}
int z[] = {1,2};
for (int y : z) {
work();
work();
work();
(void)y;
}
int empty[] = {};
for (int y : empty) {
work();
work();
work();
(void)y;
}
for (int i = 0; ; ++i) {
work();
if (i == b())
break;
}
int i;
for (i = 0; i != b(); ++i) {
work();
*(volatile int *)0 = 1;
}
for (; i != b(); ++i) {
work();
*(volatile int *)0 = 1;
}
for (; i != b(); ) {
work();
if (i == b())
break;
*(volatile int *)0 = 1;
}
for (;;) {
work();
if (i == b())
break;
}
*(volatile int *)0 = 1;
}
void *malloc(unsigned long);
void *realloc(void *, unsigned long);
void free(void *);
void reallocDiagnostics() {
char * buf = (char*)malloc(100);
char * tmp;
tmp = (char*)realloc(buf, 0x1000000);
if (!tmp) {
return;// expected-warning {{leak}}
}
buf = tmp;
free(buf);
}
template <typename T>
class unique_ptr {
T *ptr;
public:
explicit unique_ptr(T *p) : ptr(p) {}
~unique_ptr() { delete ptr; }
};
void test() {
int i = 0;
++i;
unique_ptr<int> p(new int[4]);
{
++i;
}
}
void longLines() {
id foo = [[NSObject alloc] init]; // leak
id bar =
[foo retain];
[bar release];
id baz = [foo
retain];
[baz release];
// This next line is intentionally longer than 80 characters.
id garply = [foo retain];
[garply release];
}
#define POINTER(T) T*
POINTER(void) testMacroInFunctionDecl(void *q) {
int *p = 0;
*p = 1;
return q;
}
namespace rdar14960554 {
class Foo {
int a = 1;
int b = 2;
int c = 3;
Foo() :
a(0),
c(3) {
// Check that we don't have an edge to the in-class initializer for 'b'.
if (b == 2)
*(volatile int *)0 = 1;
}
};
}