NoQ created this revision. NoQ added reviewers: dcoughlin, george.karpenkov. Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, kristof.beyls, xazax.hun, javed.absar.
`CallEvent::parameters()` returns an `ArrayRef<ParmVarDecl *>` and usually either delegates all the work to the underlying `Decl` or return an empty array if the underlying `Decl` is unavailable (eg., calling a symbolic function pointer). Returning an empty array is usually done with a convenient `ArrayRef(llvm::NoneType)` constructor: `return None;`. Returning an `{}` would have the same effect, and i don't have any preferences here. At the same time, `return nullptr;` means a completely different thing: it produces an `ArrayRef` to a literal array of 1 element, and this element is equal to `nullptr`. This corresponds to the other common pattern: when something accepts an `ArrayRef`, it also automatically accepts a single element and transparently turns it into an array of 1 element, which is often convenient. The `BlockCall` kind of `CallEvent` was incorrectly returning `nullptr`. This, well, wasn't quite expected by the newly added `OSObject` support in `RetainCountChecker`. Fix `BlockCall` to return an empty parameter array when a symbolic block is called. Repository: rC Clang https://reviews.llvm.org/D55671 Files: lib/StaticAnalyzer/Core/CallEvent.cpp test/Analysis/osobject-retain-release.cpp Index: test/Analysis/osobject-retain-release.cpp =================================================================== --- test/Analysis/osobject-retain-release.cpp +++ test/Analysis/osobject-retain-release.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,osx -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-output=text\ +// RUN: -analyzer-checker=core,osx -verify %s struct OSMetaClass; @@ -399,3 +400,11 @@ arr->release(); // +0 return arr->getCount(); } + +OSObject *getObject(); +typedef bool (^Blk)(OSObject *); + +void test_escape_to_unknown_block(Blk blk) { + blk(getObject()); // no-crash +} + Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -837,7 +837,7 @@ ArrayRef<ParmVarDecl*> BlockCall::parameters() const { const BlockDecl *D = getDecl(); if (!D) - return nullptr; + return None; return D->parameters(); }
Index: test/Analysis/osobject-retain-release.cpp =================================================================== --- test/Analysis/osobject-retain-release.cpp +++ test/Analysis/osobject-retain-release.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,osx -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-output=text\ +// RUN: -analyzer-checker=core,osx -verify %s struct OSMetaClass; @@ -399,3 +400,11 @@ arr->release(); // +0 return arr->getCount(); } + +OSObject *getObject(); +typedef bool (^Blk)(OSObject *); + +void test_escape_to_unknown_block(Blk blk) { + blk(getObject()); // no-crash +} + Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -837,7 +837,7 @@ ArrayRef<ParmVarDecl*> BlockCall::parameters() const { const BlockDecl *D = getDecl(); if (!D) - return nullptr; + return None; return D->parameters(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits