diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ObjCMessage.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ObjCMessage.cpp | 175 |
1 files changed, 0 insertions, 175 deletions
diff --git a/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/lib/StaticAnalyzer/Core/ObjCMessage.cpp deleted file mode 100644 index a00eece506..0000000000 --- a/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines ObjCMessage which serves as a common wrapper for ObjC -// message expressions or implicit messages for loading/storing ObjC properties. -// -//===----------------------------------------------------------------------===// - -#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" -#include "clang/AST/DeclCXX.h" - -using namespace clang; -using namespace ento; - -QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { - QualType resultTy; - bool isLVal = false; - - if (isObjCMessage()) { - resultTy = Msg.getResultType(ctx); - } else if (const CXXConstructExpr *Ctor = - CallE.dyn_cast<const CXXConstructExpr *>()) { - resultTy = Ctor->getType(); - } else { - const CallExpr *FunctionCall = CallE.get<const CallExpr *>(); - - isLVal = FunctionCall->isGLValue(); - const Expr *Callee = FunctionCall->getCallee(); - if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl()) - resultTy = FD->getResultType(); - else - resultTy = FunctionCall->getType(); - } - - if (isLVal) - resultTy = ctx.getPointerType(resultTy); - - return resultTy; -} - -SVal CallOrObjCMessage::getFunctionCallee() const { - assert(isFunctionCall()); - assert(!isCXXCall()); - const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens(); - return State->getSVal(Fun, LCtx); -} - -SVal CallOrObjCMessage::getCXXCallee() const { - assert(isCXXCall()); - const CallExpr *ActualCall = CallE.get<const CallExpr *>(); - const Expr *callee = - cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument(); - - // FIXME: Will eventually need to cope with member pointers. This is - // a limitation in getImplicitObjectArgument(). - if (!callee) - return UnknownVal(); - - return State->getSVal(callee, LCtx); -} - -SVal -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; -} - -bool CallOrObjCMessage::isCallbackArg(unsigned Idx, const Type *T) const { - // 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() || - T->isObjCSelType()) - 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; -} - -bool CallOrObjCMessage::hasNonZeroCallbackArg() const { - unsigned NumOfArgs = getNumArgs(); - - // Process ObjC message first. - if (!CallE) { - const ObjCMethodDecl *D = Msg.getMethodDecl(); - unsigned Idx = 0; - for (ObjCMethodDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); I != E; ++I, ++Idx) { - if (NumOfArgs <= Idx) - break; - - if (isCallbackArg(Idx, (*I)->getType().getTypePtr())) - return true; - } - return false; - } - - // Else, assume we are dealing with a Function call. - const FunctionDecl *FD = 0; - if (const CXXConstructExpr *Ctor = - CallE.dyn_cast<const CXXConstructExpr *>()) - FD = Ctor->getConstructor(); - - const CallExpr * CE = CallE.get<const CallExpr *>(); - FD = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); - - // If calling using a function pointer, assume the function does not - // have a callback. TODO: We could check the types of the arguments here. - if (!FD) - return false; - - unsigned Idx = 0; - for (FunctionDecl::param_const_iterator I = FD->param_begin(), - E = FD->param_end(); I != E; ++I, ++Idx) { - if (NumOfArgs <= Idx) - break; - - if (isCallbackArg(Idx, (*I)->getType().getTypePtr())) - return true; - } - return false; -} - -bool CallOrObjCMessage::isCFCGAllowingEscape(StringRef FName) { - if (!FName.startswith("CF") && !FName.startswith("CG")) - return false; - - return StrInStrNoCase(FName, "InsertValue") != StringRef::npos || - StrInStrNoCase(FName, "AddValue") != StringRef::npos || - StrInStrNoCase(FName, "SetValue") != StringRef::npos || - StrInStrNoCase(FName, "WithData") != StringRef::npos || - StrInStrNoCase(FName, "AppendValue") != StringRef::npos || - StrInStrNoCase(FName, "SetAttribute") != StringRef::npos; -} - - |