mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 12:46:51 +00:00

We have a new policy in place making links to private resources something we try to avoid in source and test files. Normally, we'd organically switch to the new policy rather than make a sweeping change across a project. However, Clang is in a somewhat special circumstance currently: recently, I've had several new contributors run into rdar links around test code which their patch was changing the behavior of. This turns out to be a surprisingly bad experience, especially for newer folks, for a handful of reasons: not understanding what the link is and feeling intimidated by it, wondering whether their changes are actually breaking something important to a downstream in some way, having to hunt down strangers not involved with the patch to impose on them for help, accidental pressure from asking for potentially private IP to be made public, etc. Because folks run into these links entirely by chance (through fixing bugs or working on new features), there's not really a set of problematic links to focus on -- all of the links have basically the same potential for causing these problems. As a result, this is an omnibus patch to remove all such links. This was not a mechanical change; it was done by manually searching for rdar, radar, radr, and other variants to find all the various problematic links. From there, I tried to retain or reword the surrounding comments so that we would lose as little context as possible. However, because most links were just a plain link with no supporting context, the majority of the changes are simple removals. Differential Review: https://reviews.llvm.org/D158071
592 lines
10 KiB
Plaintext
592 lines
10 KiB
Plaintext
// 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.
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
|
||
// 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.
|
||
@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.
|
||
- (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;
|
||
}
|
||
};
|
||
}
|
||
|