2018-08-30 04:29:17 +08:00
|
|
|
|
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-output=plist -o %t -w %s
|
2018-09-17 18:19:46 +08:00
|
|
|
|
// RUN: cat %t | %diff_plist %S/Inputs/expected-plists/edges-new.mm.plist
|
2013-05-24 05:33:12 +08:00
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Forward declarations (from headers).
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
typedef const struct __CFNumber * CFNumberRef;
|
|
|
|
|
typedef const struct __CFAllocator * CFAllocatorRef;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
extern const CFAllocatorRef kCFAllocatorDefault;
|
2013-05-24 05:33:12 +08:00
|
|
|
|
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);
|
|
|
|
|
|
2013-05-30 09:05:58 +08:00
|
|
|
|
#define nil ((id)0)
|
2013-05-24 05:33:12 +08:00
|
|
|
|
|
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
|
@interface NSObject
|
|
|
|
|
+ (instancetype) alloc;
|
|
|
|
|
- (instancetype) init;
|
2013-06-04 07:00:05 +08:00
|
|
|
|
- (instancetype)retain;
|
|
|
|
|
- (void)release;
|
2013-05-24 05:33:12 +08:00
|
|
|
|
@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);
|
2017-03-04 02:02:02 +08:00
|
|
|
|
|
2013-05-24 05:33:12 +08:00
|
|
|
|
*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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 06:59:56 +08:00
|
|
|
|
void test_logical_or_call() {
|
|
|
|
|
extern int call(int);
|
|
|
|
|
int *p = 0;
|
|
|
|
|
if (call(0 || 2)) {
|
|
|
|
|
*p = 0xDEADBEEF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 06:59:53 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-24 05:33:12 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-25 05:43:05 +08:00
|
|
|
|
// 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());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 05:33:12 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// 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
|
|
|
|
|
|
2013-05-30 09:05:58 +08:00
|
|
|
|
void variousLoops(id input) {
|
|
|
|
|
extern int a();
|
|
|
|
|
extern int b();
|
|
|
|
|
extern int c();
|
|
|
|
|
|
|
|
|
|
extern int work();
|
|
|
|
|
|
|
|
|
|
while (a()) {
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
work();
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
int first = 1;
|
|
|
|
|
do {
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
if (!first)
|
|
|
|
|
*(volatile int *)0 = 1;
|
|
|
|
|
first = 0;
|
|
|
|
|
} while (a());
|
|
|
|
|
|
2013-05-30 09:05:58 +08:00
|
|
|
|
for (int i = 0; i != b(); ++i) {
|
|
|
|
|
work();
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (id x in input) {
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
(void)x;
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
int z[] = {1,2};
|
2013-05-30 09:05:58 +08:00
|
|
|
|
for (int y : z) {
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
(void)y;
|
|
|
|
|
}
|
|
|
|
|
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
int empty[] = {};
|
|
|
|
|
for (int y : empty) {
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
work();
|
|
|
|
|
(void)y;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-30 09:05:58 +08:00
|
|
|
|
for (int i = 0; ; ++i) {
|
|
|
|
|
work();
|
|
|
|
|
if (i == b())
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i != b(); ++i) {
|
|
|
|
|
work();
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (; i != b(); ++i) {
|
|
|
|
|
work();
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (; i != b(); ) {
|
|
|
|
|
work();
|
|
|
|
|
if (i == b())
|
|
|
|
|
break;
|
[analyzer; new edges] Simplify edges in a C++11 for-range loop.
Previously our edges were completely broken here; now, the final result
is a very simple set of edges in most cases: one up to the "for" keyword
for context, and one into the body of the loop. This matches the behavior
for ObjC for-in loops.
In the AST, however, CXXForRangeStmts are handled very differently from
ObjCForCollectionStmts. Since they are specified in terms of equivalent
statements in the C++ standard, we actually have implicit AST nodes for
all of the semantic statements. This makes evaluation very easy, but
diagnostic locations a bit trickier. Fortunately, the problem can be
generally defined away by marking all of the implicit statements as
part of the top-level for-range statement.
One of the implicit statements in a for-range statement is the declaration
of implicit iterators __begin and __end. The CFG synthesizes two
separate DeclStmts to match each of these decls, but until now these
synthetic DeclStmts weren't in the function's ParentMap. Now, the CFG
keeps track of its synthetic statements, and the AnalysisDeclContext will
make sure to add them to the ParentMap.
<rdar://problem/14038483>
llvm-svn: 183449
2013-06-07 05:53:45 +08:00
|
|
|
|
*(volatile int *)0 = 1;
|
2013-05-30 09:05:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
work();
|
|
|
|
|
if (i == b())
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(volatile int *)0 = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 07:00:00 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 07:00:05 +08:00
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-06 08:12:41 +08:00
|
|
|
|
#define POINTER(T) T*
|
|
|
|
|
POINTER(void) testMacroInFunctionDecl(void *q) {
|
|
|
|
|
int *p = 0;
|
|
|
|
|
*p = 1;
|
|
|
|
|
return q;
|
|
|
|
|
}
|
2013-06-04 07:00:00 +08:00
|
|
|
|
|
2013-10-17 01:45:35 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|