diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ObjCMessage.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ObjCMessage.cpp | 118 |
1 files changed, 22 insertions, 96 deletions
diff --git a/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/lib/StaticAnalyzer/Core/ObjCMessage.cpp index 0974fe8..65cdcd9 100644 --- a/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ b/lib/StaticAnalyzer/Core/ObjCMessage.cpp @@ -13,108 +13,16 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" +#include "clang/AST/DeclCXX.h" 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 *>()) { @@ -124,7 +32,7 @@ QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { isLVal = FunctionCall->isLValue(); const Expr *Callee = FunctionCall->getCallee(); - if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl()) + if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl()) resultTy = FD->getResultType(); else resultTy = FunctionCall->getType(); @@ -140,7 +48,7 @@ SVal CallOrObjCMessage::getFunctionCallee() const { assert(isFunctionCall()); assert(!isCXXCall()); const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens(); - return State->getSVal(Fun); + return State->getSVal(Fun, LCtx); } SVal CallOrObjCMessage::getCXXCallee() const { @@ -154,7 +62,7 @@ SVal CallOrObjCMessage::getCXXCallee() const { if (!callee) return UnknownVal(); - return State->getSVal(callee); + return State->getSVal(callee, LCtx); } SVal @@ -162,3 +70,21 @@ CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const { assert(isObjCMessage()); return Msg.getInstanceReceiverSVal(State, LC); } + +const Decl *CallOrObjCMessage::getDecl() const { + if (isCXXCall()) { + const CXXMemberCallExpr *CE = + cast<CXXMemberCallExpr>(CallE.dyn_cast<const CallExpr *>()); + assert(CE); + return CE->getMethodDecl(); + } else if (isObjCMessage()) { + return Msg.getMethodDecl(); + } else if (isFunctionCall()) { + // In case of a C style call, use the path sensitive information to find + // the function declaration. + SVal CalleeVal = getFunctionCallee(); + return CalleeVal.getAsFunctionDecl(); + } + return 0; +} + |