diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/Analysis/dynamic-cast.cpp | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/Analysis/dynamic-cast.cpp')
-rw-r--r-- | clang/test/Analysis/dynamic-cast.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/clang/test/Analysis/dynamic-cast.cpp b/clang/test/Analysis/dynamic-cast.cpp new file mode 100644 index 0000000..8e63b2b --- /dev/null +++ b/clang/test/Analysis/dynamic-cast.cpp @@ -0,0 +1,230 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core -verify %s + +class A { +public: + virtual void f(){}; + +}; +class B : public A{ +public: + int m; +}; +class C : public A{}; + +class BB: public B{}; + +// A lot of the tests below have the if statement in them, which forces the +// analyzer to explore both path - when the result is 0 and not. This makes +// sure that we definitely know that the result is non-0 (as the result of +// the cast). +int testDynCastFromRadar() { + B aa; + A *a = &aa; + const int* res = 0; + B *b = dynamic_cast<B*>(a); + static const int i = 5; + if(b) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testBaseToBase1() { + B b; + B *pb = &b; + B *pbb = dynamic_cast<B*>(pb); + const int* res = 0; + static const int i = 5; + if (pbb) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testMultipleLevelsOfSubclassing1() { + BB bb; + B *pb = &bb; + A *pa = pb; + B *b = dynamic_cast<B*>(pa); + const int* res = 0; + static const int i = 5; + if (b) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testMultipleLevelsOfSubclassing2() { + BB bb; + A *pbb = &bb; + B *b = dynamic_cast<B*>(pbb); + BB *s = dynamic_cast<BB*>(b); + const int* res = 0; + static const int i = 5; + if (s) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testMultipleLevelsOfSubclassing3() { + BB bb; + A *pbb = &bb; + B *b = dynamic_cast<B*>(pbb); + return b->m; // no warning +} + +int testLHS() { + B aa; + A *a = &aa; + return (dynamic_cast<B*>(a))->m; +} + +int testLHS2() { + B aa; + A *a = &aa; + return (*dynamic_cast<B*>(a)).m; +} + +int testDynCastUnknown2(class A *a) { + B *b = dynamic_cast<B*>(a); + return b->m; // no warning +} + +int testDynCastUnknown(class A *a) { + B *b = dynamic_cast<B*>(a); + const int* res = 0; + static const int i = 5; + if (b) { + res = &i; + } else { + res = 0; + } + return *res; // expected-warning {{Dereference of null pointer}} +} + +int testDynCastFail2() { + C c; + A *pa = &c; + B *b = dynamic_cast<B*>(pa); + return b->m; // expected-warning {{dereference of a null pointer}} +} + +int testLHSFail() { + C c; + A *a = &c; + return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}} +} + +int testBaseToDerivedFail() { + A a; + B *b = dynamic_cast<B*>(&a); + return b->m; // expected-warning {{dereference of a null pointer}} +} + +int testConstZeroFail() { + B *b = dynamic_cast<B*>((A *)0); + return b->m; // expected-warning {{dereference of a null pointer}} +} + +int testConstZeroFail2() { + A *a = 0; + B *b = dynamic_cast<B*>(a); + return b->m; // expected-warning {{dereference of a null pointer}} +} + +int testUpcast() { + B b; + A *a = dynamic_cast<A*>(&b); + const int* res = 0; + static const int i = 5; + if (a) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testCastToVoidStar() { + A a; + void *b = dynamic_cast<void*>(&a); + const int* res = 0; + static const int i = 5; + if (b) { + res = &i; + } else { + res = 0; + } + return *res; // no warning +} + +int testReferenceSuccesfulCast() { + B rb; + B &b = dynamic_cast<B&>(rb); + int *x = 0; + return *x; // expected-warning {{Dereference of null pointer}} +} + +int testReferenceFailedCast() { + A a; + B &b = dynamic_cast<B&>(a); + int *x = 0; + return *x; // no warning (An exception is thrown by the cast.) +} + +// Here we allow any outcome of the cast and this is good because there is a +// situation where this will fail. So if the user has written the code in this +// way, we assume they expect the cast to succeed. +// Note, this might need special handling if we track types of symbolic casts +// and use them for dynamic_cast handling. +int testDynCastMostLikelyWillFail(C *c) { + B *b = 0; + b = dynamic_cast<B*>(c); + const int* res = 0; + static const int i = 5; + if (b) { + res = &i; + } else { + res = 0; + } + return *res; // expected-warning{{Dereference of null pointer}} +} + +class M : public B, public C {}; +void callTestDynCastMostLikelyWillFail() { + M m; + testDynCastMostLikelyWillFail(&m); +} + +// False positives/negatives. + +// Due to symbolic regions not being typed. +int testDynCastFalsePositive(BB *c) { + B *b = 0; + b = dynamic_cast<B*>(c); + const int* res = 0; + static const int i = 5; + if (b) { + res = &i; + } else { + res = 0; + } + return *res; // expected-warning{{Dereference of null pointer}} +} + +// Does not work when we new an object. +int testDynCastFail3() { + A *a = new A(); + B *b = dynamic_cast<B*>(a); + return b->m; +} + |