aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp14
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp17
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp15
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp22
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp36
7 files changed, 63 insertions, 52 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 11a9ab373c..30be60c9a6 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -300,7 +300,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
"Argument for property setter is an uninitialized value"
: "Argument in message expression is an uninitialized value";
// Check for any arguments that are uninitialized/undefined.
- PreVisitProcessArgs(C, ObjCMessageInvocation(msg, state, LCtx),
+ // FIXME: ObjCMessage is set to be removed soon.
+ PreVisitProcessArgs(C, ObjCMessageSend(msg.getMessageExpr(), state, LCtx),
bugDesc, BT_msg_arg);
}
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 29bb9c8f25..2c960921a4 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -481,8 +481,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
C.addTransition(State);
}
-static bool isFreeWhenDoneSetToZero(const ObjCMessageInvocation &Call,
- Selector &S) {
+static bool isFreeWhenDoneSetToZero(const ObjCMethodCall &Call) {
+ Selector S = Call.getSelector();
for (unsigned i = 1; i < S.getNumArgs(); ++i)
if (S.getNameForSlot(i).equals("freeWhenDone"))
if (Call.getArgSVal(i).isConstant(0))
@@ -497,7 +497,9 @@ void MallocChecker::checkPreObjCMessage(const ObjCMessage &Msg,
if (!MD)
return;
- ObjCMessageInvocation Call(Msg, C.getState(), C.getLocationContext());
+ // FIXME: ObjCMessage is going away soon.
+ ObjCMessageSend Call(Msg.getMessageExpr(), C.getState(),
+ C.getLocationContext());
Selector S = Msg.getSelector();
// If the first selector is dataWithBytesNoCopy, assume that the memory will
@@ -508,7 +510,7 @@ void MallocChecker::checkPreObjCMessage(const ObjCMessage &Msg,
if ((S.getNameForSlot(0) == "dataWithBytesNoCopy" ||
S.getNameForSlot(0) == "initWithBytesNoCopy" ||
S.getNameForSlot(0) == "initWithCharactersNoCopy") &&
- !isFreeWhenDoneSetToZero(Call, S)){
+ !isFreeWhenDoneSetToZero(Call)){
unsigned int argIdx = 0;
C.addTransition(FreeMemAux(C, Call.getArgExpr(argIdx),
Msg.getMessageExpr(), C.getState(), true));
@@ -1322,11 +1324,11 @@ bool MallocChecker::doesNotFreeMemory(const CallEvent *Call,
// TODO: If we want to be more optimistic here, we'll need to make sure that
// regions escape to C++ containers. They seem to do that even now, but for
// mysterious reasons.
- if (!(isa<FunctionCall>(Call) || isa<ObjCMessageInvocation>(Call)))
+ if (!(isa<FunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
return false;
// Check Objective-C messages by selector name.
- if (const ObjCMessageInvocation *Msg = dyn_cast<ObjCMessageInvocation>(Call)){
+ if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
// If it's not a framework call, or if it takes a callback, assume it
// can free memory.
if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg())
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index bb6ab6f2e3..c25da87405 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -209,7 +209,9 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
return;
}
- ObjCMessageInvocation MsgWrapper(msg, C.getState(), C.getLocationContext());
+ // FIXME: ObjCMessage is going away.
+ ObjCMessageSend MsgWrapper(msg.getMessageExpr(), C.getState(),
+ C.getLocationContext());
checkPostStmt(MsgWrapper, C);
// We don't check for an invalid 'self' in an obj-c message expression to cut
@@ -300,7 +302,9 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg,
CheckerContext &C) const {
- ObjCMessageInvocation MsgWrapper(Msg, C.getState(), C.getLocationContext());
+ // FIXME: ObjCMessage is going away.
+ ObjCMessageSend MsgWrapper(Msg.getMessageExpr(), C.getState(),
+ C.getLocationContext());
checkPreStmt(MsgWrapper, C);
}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index d43b2cde26..12b74e7e29 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -747,10 +747,10 @@ public:
QualType RetTy,
ObjCMethodSummariesTy &CachedSummaries);
- const RetainSummary *getInstanceMethodSummary(const ObjCMessageInvocation &M,
+ const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
ProgramStateRef State);
- const RetainSummary *getClassMethodSummary(const ObjCMessageInvocation &M) {
+ const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
assert(!M.isInstanceMessage());
const ObjCInterfaceDecl *Class = M.getReceiverInterface();
@@ -950,8 +950,9 @@ RetainSummaryManager::getSummary(const CallEvent &Call,
case CE_CXXConstructor:
// FIXME: These calls are currently unsupported.
return getPersistentStopSummary();
- case CE_ObjCMessage: {
- const ObjCMessageInvocation &Msg = cast<ObjCMessageInvocation>(Call);
+ case CE_ObjCMessage:
+ case CE_ObjCPropertyAccess: {
+ const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
if (Msg.isInstanceMessage())
Summ = getInstanceMethodSummary(Msg, State);
else
@@ -1447,7 +1448,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
}
const RetainSummary *
-RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageInvocation &Msg,
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
ProgramStateRef State) {
const ObjCInterfaceDecl *ReceiverClass = 0;
@@ -2795,7 +2796,8 @@ void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
const LocationContext *LC = C.getLocationContext();
- ObjCMessageInvocation Call(Msg, state, LC);
+ // FIXME: ObjCMessage is going away.
+ ObjCMessageSend Call(Msg.getMessageExpr(), state, LC);
RetainSummaryManager &Summaries = getSummaryManager(C);
const RetainSummary *Summ = Summaries.getSummary(Call, state);
@@ -2859,8 +2861,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
// Evaluate the effect on the message receiver.
bool ReceiverIsTracked = false;
if (!hasErr) {
- const ObjCMessageInvocation *MsgInvocation =
- dyn_cast<ObjCMessageInvocation>(&CallOrMsg);
+ const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg);
if (MsgInvocation) {
if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
if (const RefVal *T = state->get<RefBindings>(Sym)) {
diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp
index 510f8340a2..bdd4508cea 100644
--- a/lib/StaticAnalyzer/Core/Calls.cpp
+++ b/lib/StaticAnalyzer/Core/Calls.cpp
@@ -334,7 +334,7 @@ void CXXConstructorCall::addExtraInvalidatedRegions(RegionList &Regions) const {
}
-CallEvent::param_iterator ObjCMessageInvocation::param_begin() const {
+CallEvent::param_iterator ObjCMethodCall::param_begin() const {
const ObjCMethodDecl *D = getDecl();
if (!D)
return 0;
@@ -342,7 +342,7 @@ CallEvent::param_iterator ObjCMessageInvocation::param_begin() const {
return D->param_begin();
}
-CallEvent::param_iterator ObjCMessageInvocation::param_end() const {
+CallEvent::param_iterator ObjCMethodCall::param_end() const {
const ObjCMethodDecl *D = getDecl();
if (!D)
return 0;
@@ -351,12 +351,12 @@ CallEvent::param_iterator ObjCMessageInvocation::param_end() const {
}
void
-ObjCMessageInvocation::addExtraInvalidatedRegions(RegionList &Regions) const {
+ObjCMethodCall::addExtraInvalidatedRegions(RegionList &Regions) const {
if (const MemRegion *R = getReceiverSVal().getAsRegion())
Regions.push_back(R);
}
-QualType ObjCMessageInvocation::getDeclaredResultType() const {
+QualType ObjCMethodCall::getDeclaredResultType() const {
const ObjCMethodDecl *D = getDecl();
if (!D)
return QualType();
@@ -364,12 +364,12 @@ QualType ObjCMessageInvocation::getDeclaredResultType() const {
return D->getResultType();
}
-SVal ObjCMessageInvocation::getReceiverSVal() const {
+SVal ObjCMethodCall::getReceiverSVal() const {
// FIXME: Is this the best way to handle class receivers?
if (!isInstanceMessage())
return UnknownVal();
- const Expr *Base = Msg.getInstanceReceiver();
+ const Expr *Base = Msg->getInstanceReceiver();
if (Base)
return getSVal(Base);
@@ -377,5 +377,6 @@ SVal ObjCMessageInvocation::getReceiverSVal() const {
// In this case the object reference is the same as 'self'.
const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
- return loc::MemRegionVal(State->getRegion(SelfDecl, LCtx));
+ return State->getSVal(State->getRegion(SelfDecl, LCtx));
}
+
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 255d870186..141c5bbf03 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -867,26 +867,32 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCMessageExprClass: {
Bldr.takeNodes(Pred);
// Is this a property access?
- const ParentMap &PM = Pred->getLocationContext()->getParentMap();
+
+ const LocationContext *LCtx = Pred->getLocationContext();
+ const ParentMap &PM = LCtx->getParentMap();
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(S);
bool evaluated = false;
if (const PseudoObjectExpr *PO =
- dyn_cast_or_null<PseudoObjectExpr>(PM.getParent(S))) {
+ dyn_cast_or_null<PseudoObjectExpr>(PM.getParent(S))) {
const Expr *syntactic = PO->getSyntacticForm();
+
+ // This handles the funny case of assigning to the result of a getter.
+ // This can happen if the getter returns a non-const reference.
+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(syntactic))
+ syntactic = BO->getLHS();
+
if (const ObjCPropertyRefExpr *PR =
dyn_cast<ObjCPropertyRefExpr>(syntactic)) {
- bool isSetter = ME->getNumArgs() > 0;
- VisitObjCMessage(ObjCMessage(ME, PR, isSetter), Pred, Dst);
+ VisitObjCMessage(ObjCPropertyAccess(PR, ME, Pred->getState(), LCtx),
+ Pred, Dst);
evaluated = true;
}
- else if (isa<BinaryOperator>(syntactic)) {
- VisitObjCMessage(ObjCMessage(ME, 0, true), Pred, Dst);
- }
}
if (!evaluated)
- VisitObjCMessage(ME, Pred, Dst);
+ VisitObjCMessage(ObjCMessageSend(ME, Pred->getState(), LCtx),
+ Pred, Dst);
Bldr.addNodes(Dst);
break;
diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index d35d999b5e..86630a8c02 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -141,7 +141,7 @@ static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
return isSubclass(Class->getSuperClass(), II);
}
-void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
+void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -160,18 +160,20 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
ExplodedNode *Pred = *DI;
bool RaisesException = false;
- if (const Expr *Receiver = msg.getInstanceReceiver()) {
- ProgramStateRef state = Pred->getState();
- SVal recVal = state->getSVal(Receiver, Pred->getLocationContext());
+ if (msg.isInstanceMessage()) {
+ SVal recVal = msg.getReceiverSVal();
if (!recVal.isUndef()) {
// Bifurcate the state into nil and non-nil ones.
DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
+ ProgramStateRef state = Pred->getState();
ProgramStateRef notNilState, nilState;
llvm::tie(notNilState, nilState) = state->assume(receiverVal);
// There are three cases: can be nil or non-nil, must be nil, must be
// non-nil. We ignore must be nil, and merge the rest two into non-nil.
+ // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
+ // Revisit once we have lazier constraints.
if (nilState && !notNilState) {
continue;
}
@@ -186,12 +188,9 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
// Dispatch to plug-in transfer function.
evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException);
}
- } else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
- // Note that this branch also handles messages to super, not just
- // class methods!
-
+ } else {
// Check for special class methods.
- if (!msg.isInstanceMessage()) {
+ if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
if (!NSExceptionII) {
ASTContext &Ctx = getContext();
NSExceptionII = &Ctx.Idents.get("NSException");
@@ -243,13 +242,10 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
}
void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
- const ObjCMessage &msg,
+ const ObjCMethodCall &msg,
ExplodedNode *Pred,
ProgramStateRef state,
bool GenSink) {
- const LocationContext *LCtx = Pred->getLocationContext();
- unsigned BlockCount = currentBuilderContext->getCurrentBlockCount();
-
// First handle the return value.
SVal ReturnValue = UnknownVal();
@@ -261,17 +257,18 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
case OMF_retain:
case OMF_self: {
// These methods return their receivers.
- const Expr *ReceiverE = msg.getInstanceReceiver();
- if (ReceiverE)
- ReturnValue = state->getSVal(ReceiverE, LCtx);
+ ReturnValue = msg.getReceiverSVal();
break;
}
}
+ const LocationContext *LCtx = Pred->getLocationContext();
+ unsigned BlockCount = currentBuilderContext->getCurrentBlockCount();
+
// If we failed to figure out the return value, use a conjured value instead.
if (ReturnValue.isUnknown()) {
SValBuilder &SVB = getSValBuilder();
- QualType ResultTy = msg.getResultType(getContext());
+ QualType ResultTy = msg.getResultType();
const Expr *CurrentE = cast<Expr>(currentStmt);
ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, LCtx, ResultTy,
BlockCount);
@@ -281,11 +278,10 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
state = state->BindExpr(currentStmt, LCtx, ReturnValue);
// Invalidate the arguments (and the receiver)
- ObjCMessageInvocation Invocation(msg, state, LCtx);
- state = Invocation.invalidateRegions(BlockCount);
+ state = msg.invalidateRegions(BlockCount, state);
// And create the new node.
- Bldr.generateNode(msg.getMessageExpr(), Pred, state, GenSink);
+ Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink);
assert(Bldr.hasGeneratedNodes());
}