aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ObjCMessage.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-05-03 23:50:33 +0000
committerAnna Zaks <ganna@apple.com>2012-05-03 23:50:33 +0000
commitb79d862af66d8dd9d059863813b9a27d744bd990 (patch)
treea335fbede54f7af1b73ceca9467ef6af3989f145 /lib/StaticAnalyzer/Core/ObjCMessage.cpp
parentaca0ac58d2ae80d764e3832456667d7322445e0c (diff)
[analyzer] Assume pointer escapes when a callback is passed inside
a struct. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156135 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ObjCMessage.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ObjCMessage.cpp24
1 files changed, 21 insertions, 3 deletions
diff --git a/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/lib/StaticAnalyzer/Core/ObjCMessage.cpp
index dc24e818ff..0c6d8a8b63 100644
--- a/lib/StaticAnalyzer/Core/ObjCMessage.cpp
+++ b/lib/StaticAnalyzer/Core/ObjCMessage.cpp
@@ -89,10 +89,28 @@ const Decl *CallOrObjCMessage::getDecl() const {
}
bool CallOrObjCMessage::isCallbackArg(unsigned Idx, const Type *T) const {
- // Should we dig into struct fields, arrays ect?
+ // If the parameter is 0, it's harmless.
+ if (getArgSVal(Idx).isZeroConstant())
+ return false;
+
+ // If a parameter is a block or a callback, assume it can modify pointer.
if (T->isBlockPointerType() || T->isFunctionPointerType())
- if (!getArgSVal(Idx).isZeroConstant())
- return true;
+ return true;
+
+ // Check if a callback is passed inside a struct (for both, struct passed by
+ // reference and by value). Dig just one level into the struct for now.
+ if (const PointerType *PT = dyn_cast<PointerType>(T))
+ T = PT->getPointeeType().getTypePtr();
+
+ if (const RecordType *RT = T->getAsStructureType()) {
+ const RecordDecl *RD = RT->getDecl();
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I ) {
+ const Type *FieldT = I->getType().getTypePtr();
+ if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
+ return true;
+ }
+ }
return false;
}