diff options
Diffstat (limited to 'test/Analysis/new.cpp')
-rw-r--r-- | test/Analysis/new.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/test/Analysis/new.cpp b/test/Analysis/new.cpp index 8d3eee9..105a973 100644 --- a/test/Analysis/new.cpp +++ b/test/Analysis/new.cpp @@ -170,6 +170,16 @@ void testUsingThisAfterDelete() { c->f(0); // no-warning } +void testAggregateNew() { + struct Point { int x, y; }; + new Point{1, 2}; // no crash + + Point p; + new (&p) Point{1, 2}; // no crash + clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}} +} + //-------------------------------- // Incorrectly-modelled behavior //-------------------------------- @@ -196,3 +206,148 @@ int testNoInitializationPlacement() { } return 1; } + +// Test modelling destructor call on call to delete +class IntPair{ +public: + int x; + int y; + IntPair() {}; + ~IntPair() {x = x/y;}; //expected-warning {{Division by zero}} +}; + +void testCallToDestructor() { + IntPair *b = new IntPair(); + b->x = 1; + b->y = 0; + delete b; // This results in divide by zero in destructor +} + +// Test Deleting a value that's passed as an argument. +class DerefClass{ +public: + int *x; + DerefClass() {}; + ~DerefClass() {*x = 1;}; //expected-warning {{Dereference of null pointer (loaded from field 'x')}} +}; + +void testDestCall(DerefClass *arg) { + delete arg; +} + +void test_delete_dtor_Arg() { + DerefClass *pair = new DerefClass(); + pair->x = 0; + testDestCall(pair); +} + +//Deleting the address of a local variable, null pointer +void abort(void) __attribute__((noreturn)); + +class NoReturnDtor { +public: + NoReturnDtor() {} + ~NoReturnDtor() {abort();} +}; + +void test_delete_dtor_LocalVar() { + NoReturnDtor test; + delete &test; // no warn or crash +} + +class DerivedNoReturn:public NoReturnDtor { +public: + DerivedNoReturn() {}; + ~DerivedNoReturn() {}; +}; + +void testNullDtorDerived() { + DerivedNoReturn *p = new DerivedNoReturn(); + delete p; // Calls the base destructor which aborts, checked below + clang_analyzer_eval(true); // no warn +} + +//Deleting a non class pointer should not crash/warn +void test_var_delete() { + int *v = new int; + delete v; // no crash/warn + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +void testDeleteNull() { + NoReturnDtor *foo = 0; + delete foo; // should not call destructor, checked below + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +void testNullAssigneddtor() { + NoReturnDtor *p = 0; + NoReturnDtor *s = p; + delete s; // should not call destructor, checked below + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +void deleteArg(NoReturnDtor *test) { + delete test; +} + +void testNulldtorArg() { + NoReturnDtor *p = 0; + deleteArg(p); + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +void testDeleteUnknown(NoReturnDtor *foo) { + delete foo; // should assume non-null and call noreturn destructor + clang_analyzer_eval(true); // no-warning +} + +void testArrayNull() { + NoReturnDtor *fooArray = 0; + delete[] fooArray; // should not call destructor, checked below + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +void testArrayDestr() { + NoReturnDtor *p = new NoReturnDtor[2]; + delete[] p; // Calls the base destructor which aborts, checked below + //TODO: clang_analyzer_eval should not be called + clang_analyzer_eval(true); // expected-warning{{TRUE}} +} + +// Invalidate Region even in case of default destructor +class InvalidateDestTest { +public: + int x; + int *y; + ~InvalidateDestTest(); +}; + +int test_member_invalidation() { + + //test invalidation of member variable + InvalidateDestTest *test = new InvalidateDestTest(); + test->x = 5; + int *k = &(test->x); + clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}} + delete test; + clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}} + + //test invalidation of member pointer + int localVar = 5; + test = new InvalidateDestTest(); + test->y = &localVar; + delete test; + clang_analyzer_eval(localVar == 5); // expected-warning{{UNKNOWN}} + + // Test aray elements are invalidated. + int Var1 = 5; + int Var2 = 5; + InvalidateDestTest *a = new InvalidateDestTest[2]; + a[0].y = &Var1; + a[1].y = &Var2; + delete[] a; + clang_analyzer_eval(Var1 == 5); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(Var2 == 5); // expected-warning{{UNKNOWN}} + return 0; +} |