mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-29 00:08:59 -04:00

Previously, this was scattered across Environment (literal expressions), ExprEngine (default arguments), and RegionStore (global constants). The former special-cased several kinds of simple constant expressions, while the latter two deferred to the AST's constant evaluator. Now, these are all unified as SValBuilder::getConstantVal(). To keep Environment fast, the special cases for simple constant expressions have been left in, but the main benefits are that (a) unusual constants like ObjCStringLiterals now work as default arguments and global constant initializers, and (b) we're not duplicating code between ExprEngine and RegionStore. This actually caught a bug in our test suite, which is awesome: we stop tracking allocated memory if it's passed as an argument along with some kind of callback, but not if the callback is 0. We were testing this in a case where the callback parameter had a default value, but that value was 0. After this change, the analyzer now (correctly) flags that as a leak! <rdar://problem/13773117> llvm-svn: 180894
108 lines
2.7 KiB
C++
108 lines
2.7 KiB
C++
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc -analyzer-store=region -verify %s
|
|
|
|
typedef __typeof(sizeof(int)) size_t;
|
|
void *malloc(size_t);
|
|
void free(void *);
|
|
void *realloc(void *ptr, size_t size);
|
|
void *calloc(size_t nmemb, size_t size);
|
|
char *strdup(const char *s);
|
|
|
|
void checkThatMallocCheckerIsRunning() {
|
|
malloc(4);
|
|
} // expected-warning{{leak}}
|
|
|
|
// Test for radar://11110132.
|
|
struct Foo {
|
|
mutable void* m_data;
|
|
Foo(void* data) : m_data(data) {}
|
|
};
|
|
Foo aFunction() {
|
|
return malloc(10);
|
|
}
|
|
|
|
// Assume that functions which take a function pointer can free memory even if
|
|
// they are defined in system headers and take the const pointer to the
|
|
// allocated memory. (radar://11160612)
|
|
// Test default parameter.
|
|
int const_ptr_and_callback_def_param(int, const char*, int n, void(*)(void*) = free);
|
|
void r11160612_3() {
|
|
char *x = (char*)malloc(12);
|
|
const_ptr_and_callback_def_param(0, x, 12);
|
|
}
|
|
|
|
int const_ptr_and_callback_def_param_null(int, const char*, int n, void(*)(void*) = 0);
|
|
void r11160612_no_callback() {
|
|
char *x = (char*)malloc(12);
|
|
const_ptr_and_callback_def_param_null(0, x, 12);
|
|
} // expected-warning{{leak}}
|
|
|
|
// Test member function pointer.
|
|
struct CanFreeMemory {
|
|
static void myFree(void*);
|
|
};
|
|
//This is handled because we look at the type of the parameter(not argument).
|
|
void r11160612_3(CanFreeMemory* p) {
|
|
char *x = (char*)malloc(12);
|
|
const_ptr_and_callback_def_param(0, x, 12, p->myFree);
|
|
}
|
|
|
|
|
|
namespace PR13751 {
|
|
class OwningVector {
|
|
void **storage;
|
|
size_t length;
|
|
public:
|
|
OwningVector();
|
|
~OwningVector();
|
|
void push_back(void *Item) {
|
|
storage[length++] = Item;
|
|
}
|
|
};
|
|
|
|
void testDestructors() {
|
|
OwningVector v;
|
|
v.push_back(malloc(4));
|
|
// no leak warning; freed in destructor
|
|
}
|
|
}
|
|
|
|
struct X { void *a; };
|
|
|
|
struct X get() {
|
|
struct X result;
|
|
result.a = malloc(4);
|
|
return result; // no-warning
|
|
}
|
|
|
|
// Ensure that regions accessible through a LazyCompoundVal trigger region escape.
|
|
// Malloc checker used to report leaks for the following two test cases.
|
|
struct Property {
|
|
char* getterName;
|
|
Property(char* n)
|
|
: getterName(n) {}
|
|
|
|
};
|
|
void append(Property x);
|
|
|
|
void appendWrapper(char *getterName) {
|
|
append(Property(getterName));
|
|
}
|
|
void foo(const char* name) {
|
|
char* getterName = strdup(name);
|
|
appendWrapper(getterName); // no-warning
|
|
}
|
|
|
|
struct NestedProperty {
|
|
Property prop;
|
|
NestedProperty(Property p)
|
|
: prop(p) {}
|
|
};
|
|
void appendNested(NestedProperty x);
|
|
|
|
void appendWrapperNested(char *getterName) {
|
|
appendNested(NestedProperty(Property(getterName)));
|
|
}
|
|
void fooNested(const char* name) {
|
|
char* getterName = strdup(name);
|
|
appendWrapperNested(getterName); // no-warning
|
|
} |