diff options
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp | 25 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 34 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ObjCMessage.cpp | 93 |
6 files changed, 50 insertions, 112 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 88a3be4139..3a4c15f0d2 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -32,6 +32,7 @@ class CallAndMessageChecker mutable OwningPtr<BugType> BT_call_undef; mutable OwningPtr<BugType> BT_call_arg; mutable OwningPtr<BugType> BT_msg_undef; + mutable OwningPtr<BugType> BT_objc_prop_undef; mutable OwningPtr<BugType> BT_msg_arg; mutable OwningPtr<BugType> BT_msg_ret; public: @@ -228,11 +229,21 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, SVal recVal = state->getSVal(receiver, LCtx); if (recVal.isUndef()) { if (ExplodedNode *N = C.generateSink()) { - if (!BT_msg_undef) - BT_msg_undef.reset(new BuiltinBug("Receiver in message expression is " - "an uninitialized value")); + BugType *BT = 0; + if (msg.isPureMessageExpr()) { + if (!BT_msg_undef) + BT_msg_undef.reset(new BuiltinBug("Receiver in message expression " + "is an uninitialized value")); + BT = BT_msg_undef.get(); + } + else { + if (!BT_objc_prop_undef) + BT_objc_prop_undef.reset(new BuiltinBug("Property access on an " + "uninitialized object pointer")); + BT = BT_objc_prop_undef.get(); + } BugReport *R = - new BugReport(*BT_msg_undef, BT_msg_undef->getName(), N); + new BugReport(*BT, BT->getName(), N); R->addRange(receiver->getSourceRange()); R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, receiver)); @@ -306,13 +317,13 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, if (CanRetTy->isStructureOrClassType()) { // Structure returns are safe since the compiler zeroes them out. SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx)); - C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V)); + C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V)); return; } // Other cases: check if sizeof(return type) > sizeof(void*) if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap() - .isConsumedExpr(msg.getOriginExpr())) { + .isConsumedExpr(msg.getMessageExpr())) { // Compute: sizeof(void *) and sizeof(return type) const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy); @@ -343,7 +354,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, // of this case unless we have *a lot* more knowledge. // SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx)); - C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V)); + C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V)); return; } diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index dbbab4891c..165dff5b10 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -196,7 +196,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, // value out when we return from this method. state = state->set<CalledInit>(true); - SVal V = state->getSVal(msg.getOriginExpr(), C.getLocationContext()); + SVal V = state->getSVal(msg.getMessageExpr(), C.getLocationContext()); addSelfFlag(state, V, SelfFlag_InitRes, C); return; } diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index cb4da7cf4c..6f7a47fb8f 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -190,8 +190,10 @@ namespace { NodeBuilder &Bldr, ExplodedNode *Pred) { ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : ProgramPoint::PostStmtKind; - const ProgramPoint &L = ProgramPoint::getProgramPoint(Msg.getOriginExpr(), - K, Pred->getLocationContext(), checkFn.Checker); + const ProgramPoint &L = + ProgramPoint::getProgramPoint(Msg.getMessageExpr(), + K, Pred->getLocationContext(), + checkFn.Checker); CheckerContext C(Bldr, Eng, Pred, L); checkFn(Msg, C); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6f588c5ae1..34ad23a429 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -808,11 +808,33 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); break; - case Stmt::ObjCMessageExprClass: + case Stmt::ObjCMessageExprClass: { Bldr.takeNodes(Pred); - VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst); + // Is this a property access? + const ParentMap &PM = Pred->getLocationContext()->getParentMap(); + const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(S); + bool evaluated = false; + + if (const PseudoObjectExpr *PO = + dyn_cast_or_null<PseudoObjectExpr>(PM.getParent(S))) { + const Expr *syntactic = PO->getSyntacticForm(); + if (const ObjCPropertyRefExpr *PR = + dyn_cast<ObjCPropertyRefExpr>(syntactic)) { + bool isSetter = ME->getNumArgs() > 0; + VisitObjCMessage(ObjCMessage(ME, PR, isSetter), Pred, Dst); + evaluated = true; + } + else if (isa<BinaryOperator>(syntactic)) { + VisitObjCMessage(ObjCMessage(ME, 0, true), Pred, Dst); + } + } + + if (!evaluated) + VisitObjCMessage(ME, Pred, Dst); + Bldr.addNodes(Dst); break; + } case Stmt::ObjCAtThrowStmtClass: { // FIXME: This is not complete. We basically treat @throw as @@ -1439,9 +1461,7 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE = AssignE ? AssignE : LocationE; if (isa<loc::ObjCPropRef>(location)) { - loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location); - return VisitObjCMessage(ObjCPropertySetter(prop.getPropRefExpr(), - StoreE, Val), Pred, Dst); + assert(false); } // Evaluate the location (checks for bad dereferences). @@ -1466,9 +1486,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, assert(!isa<NonLoc>(location) && "location cannot be a NonLoc."); if (isa<loc::ObjCPropRef>(location)) { - loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location); - return VisitObjCMessage(ObjCPropertyGetter(prop.getPropRefExpr(), Ex), - Pred, Dst); + assert(false); } // Are we loading from a region? This actually results in two loads; one diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index b5ceb64fab..72d03a1585 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -267,7 +267,7 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, state = invalidateArguments(state, CallOrObjCMessage(msg, state, LCtx), LCtx); // And create the new node. - Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink); + Bldr.generateNode(msg.getMessageExpr(), Pred, state, GenSink); assert(Bldr.hasGeneratedNodes()); } diff --git a/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/lib/StaticAnalyzer/Core/ObjCMessage.cpp index ac571a5ef6..65cdcd9d99 100644 --- a/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ b/lib/StaticAnalyzer/Core/ObjCMessage.cpp @@ -18,104 +18,11 @@ using namespace clang; using namespace ento; -QualType ObjCMessage::getType(ASTContext &ctx) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getType(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (isPropertySetter()) - return ctx.VoidTy; - return propE->getType(); -} - -Selector ObjCMessage::getSelector() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getSelector(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (isPropertySetter()) - return propE->getSetterSelector(); - return propE->getGetterSelector(); -} - -ObjCMethodFamily ObjCMessage::getMethodFamily() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - // Case 1. Explicit message send. - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getMethodFamily(); - - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - - // Case 2. Reference to implicit property. - if (propE->isImplicitProperty()) { - if (isPropertySetter()) - return propE->getImplicitPropertySetter()->getMethodFamily(); - else - return propE->getImplicitPropertyGetter()->getMethodFamily(); - } - - // Case 3. Reference to explicit property. - const ObjCPropertyDecl *prop = propE->getExplicitProperty(); - if (isPropertySetter()) { - if (prop->getSetterMethodDecl()) - return prop->getSetterMethodDecl()->getMethodFamily(); - return prop->getSetterName().getMethodFamily(); - } else { - if (prop->getGetterMethodDecl()) - return prop->getGetterMethodDecl()->getMethodFamily(); - return prop->getGetterName().getMethodFamily(); - } -} - -const ObjCMethodDecl *ObjCMessage::getMethodDecl() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getMethodDecl(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (propE->isImplicitProperty()) - return isPropertySetter() ? propE->getImplicitPropertySetter() - : propE->getImplicitPropertyGetter(); - return 0; -} - -const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getReceiverInterface(); - const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); - if (propE->isClassReceiver()) - return propE->getClassReceiver(); - QualType recT; - if (const Expr *recE = getInstanceReceiver()) - recT = recE->getType(); - else { - assert(propE->isSuperReceiver()); - recT = propE->getSuperReceiverType(); - } - if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>()) - return Ptr->getInterfaceDecl(); - return 0; -} - -const Expr *ObjCMessage::getArgExpr(unsigned i) const { - assert(isValid() && "This ObjCMessage is uninitialized!"); - assert(i < getNumArgs() && "Invalid index for argument"); - if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) - return msgE->getArg(i); - assert(isPropertySetter()); - if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE)) - if (bop->isAssignmentOp()) - return bop->getRHS(); - return 0; -} - QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { QualType resultTy; bool isLVal = false; if (isObjCMessage()) { - isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) && - Msg.getOriginExpr()->isLValue(); resultTy = Msg.getResultType(ctx); } else if (const CXXConstructExpr *Ctor = CallE.dyn_cast<const CXXConstructExpr *>()) { |