diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2018-10-25 23:38:07 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2018-10-25 23:38:07 +0000 |
| commit | 3c2ed8f3386eebae956267998c2d9aaec9105181 (patch) | |
| tree | 267893d5d34bec7e9ddb5247e277c6988ccb64a2 /clang/test | |
| parent | f0923f16f88519a8eed863c93bbf5086e4420a3a (diff) | |
| download | bcm5719-llvm-3c2ed8f3386eebae956267998c2d9aaec9105181.tar.gz bcm5719-llvm-3c2ed8f3386eebae956267998c2d9aaec9105181.zip | |
[analyzer] Correct modelling of OSDynamicCast: eagerly state split
Previously, OSDynamicCast was modeled as an identity.
This is not correct: the output of OSDynamicCast may be zero even if the
input was not zero (if the class is not of desired type), and thus the
modeling led to false positives.
Instead, we are doing eager state split:
in one branch, the returned value is identical to the input parameter,
and in the other branch, the returned value is zero.
This patch required a substantial refactoring of canEval infrastructure,
as now it can return different function summaries, and not just true/false.
rdar://45497400
Differential Revision: https://reviews.llvm.org/D53624
llvm-svn: 345338
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/osobject-retain-release.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/clang/test/Analysis/osobject-retain-release.cpp b/clang/test/Analysis/osobject-retain-release.cpp index 23e92ecaf6b..4e26c03bc26 100644 --- a/clang/test/Analysis/osobject-retain-release.cpp +++ b/clang/test/Analysis/osobject-retain-release.cpp @@ -17,6 +17,8 @@ struct OSObject { virtual void release() {}; virtual ~OSObject(){} + unsigned int foo() { return 42; } + static OSObject *generateObject(int); static const OSMetaClass * const metaClass; @@ -78,8 +80,31 @@ void check_dynamic_cast() { arr->release(); } +unsigned int check_dynamic_cast_no_null_on_orig(OSObject *obj) { + OSArray *arr = OSDynamicCast(OSArray, obj); + if (arr) { + return arr->getCount(); + } else { + + // The fact that dynamic cast has failed should not imply that + // the input object was null. + return obj->foo(); // no-warning + } +} + +void check_dynamic_cast_null_branch(OSObject *obj) { + OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject}} + OSArray *arr = OSDynamicCast(OSArray, obj); + if (!arr) // expected-note{{Taking true branch}} + return; // expected-warning{{Potential leak}} + // expected-note@-1{{Object leaked}} + arr1->release(); +} + void check_dynamic_cast_null_check() { - OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); + OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to function 'generateObject' returns an OSObject}} + // expected-warning@-1{{Potential leak of an object}} + // expected-note@-2{{Object leaked}} if (!arr) return; arr->release(); |

