Home | History | Annotate | Download | only in Core
      1 //===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines ObjCMessage which serves as a common wrapper for ObjC
     11 // message expressions or implicit messages for loading/storing ObjC properties.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
     16 #include "clang/AST/DeclCXX.h"
     17 
     18 using namespace clang;
     19 using namespace ento;
     20 
     21 QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
     22   QualType resultTy;
     23   bool isLVal = false;
     24 
     25   if (isObjCMessage()) {
     26     resultTy = Msg.getResultType(ctx);
     27   } else if (const CXXConstructExpr *Ctor =
     28               CallE.dyn_cast<const CXXConstructExpr *>()) {
     29     resultTy = Ctor->getType();
     30   } else {
     31     const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
     32 
     33     isLVal = FunctionCall->isLValue();
     34     const Expr *Callee = FunctionCall->getCallee();
     35     if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl())
     36       resultTy = FD->getResultType();
     37     else
     38       resultTy = FunctionCall->getType();
     39   }
     40 
     41   if (isLVal)
     42     resultTy = ctx.getPointerType(resultTy);
     43 
     44   return resultTy;
     45 }
     46 
     47 SVal CallOrObjCMessage::getFunctionCallee() const {
     48   assert(isFunctionCall());
     49   assert(!isCXXCall());
     50   const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
     51   return State->getSVal(Fun, LCtx);
     52 }
     53 
     54 SVal CallOrObjCMessage::getCXXCallee() const {
     55   assert(isCXXCall());
     56   const CallExpr *ActualCall = CallE.get<const CallExpr *>();
     57   const Expr *callee =
     58     cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
     59 
     60   // FIXME: Will eventually need to cope with member pointers.  This is
     61   // a limitation in getImplicitObjectArgument().
     62   if (!callee)
     63     return UnknownVal();
     64 
     65   return State->getSVal(callee, LCtx);
     66 }
     67 
     68 SVal
     69 CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
     70   assert(isObjCMessage());
     71   return Msg.getInstanceReceiverSVal(State, LC);
     72 }
     73 
     74 const Decl *CallOrObjCMessage::getDecl() const {
     75   if (isCXXCall()) {
     76     const CXXMemberCallExpr *CE =
     77         cast<CXXMemberCallExpr>(CallE.dyn_cast<const CallExpr *>());
     78     assert(CE);
     79     return CE->getMethodDecl();
     80   } else if (isObjCMessage()) {
     81     return Msg.getMethodDecl();
     82   } else if (isFunctionCall()) {
     83     // In case of a C style call, use the path sensitive information to find
     84     // the function declaration.
     85     SVal CalleeVal = getFunctionCallee();
     86     return CalleeVal.getAsFunctionDecl();
     87   }
     88   return 0;
     89 }
     90 
     91