]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Core / ObjCMessage.cpp
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
17 using namespace clang;
18 using namespace ento;
19
20 QualType ObjCMessage::getType(ASTContext &ctx) const {
21   assert(isValid() && "This ObjCMessage is uninitialized!");
22   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
23     return msgE->getType();
24   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
25   if (isPropertySetter())
26     return ctx.VoidTy;
27   return propE->getType();
28 }
29
30 Selector ObjCMessage::getSelector() const {
31   assert(isValid() && "This ObjCMessage is uninitialized!");
32   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
33     return msgE->getSelector();
34   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
35   if (isPropertySetter())
36     return propE->getSetterSelector();
37   return propE->getGetterSelector();
38 }
39
40 ObjCMethodFamily ObjCMessage::getMethodFamily() const {
41   assert(isValid() && "This ObjCMessage is uninitialized!");
42   // Case 1.  Explicit message send.
43   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
44     return msgE->getMethodFamily();
45
46   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
47
48   // Case 2.  Reference to implicit property.
49   if (propE->isImplicitProperty()) {
50     if (isPropertySetter())
51       return propE->getImplicitPropertySetter()->getMethodFamily();
52     else
53       return propE->getImplicitPropertyGetter()->getMethodFamily();
54   }
55
56   // Case 3.  Reference to explicit property.
57   const ObjCPropertyDecl *prop = propE->getExplicitProperty();
58   if (isPropertySetter()) {
59     if (prop->getSetterMethodDecl())
60       return prop->getSetterMethodDecl()->getMethodFamily();
61     return prop->getSetterName().getMethodFamily();
62   } else {
63     if (prop->getGetterMethodDecl())
64       return prop->getGetterMethodDecl()->getMethodFamily();
65     return prop->getGetterName().getMethodFamily();
66   }
67 }
68
69 const ObjCMethodDecl *ObjCMessage::getMethodDecl() const {
70   assert(isValid() && "This ObjCMessage is uninitialized!");
71   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
72     return msgE->getMethodDecl();
73   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
74   if (propE->isImplicitProperty())
75     return isPropertySetter() ? propE->getImplicitPropertySetter()
76                               : propE->getImplicitPropertyGetter();
77   return 0;
78 }
79
80 const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const {
81   assert(isValid() && "This ObjCMessage is uninitialized!");
82   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
83     return msgE->getReceiverInterface();
84   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
85   if (propE->isClassReceiver())
86     return propE->getClassReceiver();
87   QualType recT;
88   if (const Expr *recE = getInstanceReceiver())
89     recT = recE->getType();
90   else {
91     assert(propE->isSuperReceiver());
92     recT = propE->getSuperReceiverType();
93   }
94   if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>())
95     return Ptr->getInterfaceDecl();
96   return 0;
97 }
98
99 const Expr *ObjCMessage::getArgExpr(unsigned i) const {
100   assert(isValid() && "This ObjCMessage is uninitialized!");
101   assert(i < getNumArgs() && "Invalid index for argument");
102   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
103     return msgE->getArg(i);
104   assert(isPropertySetter());
105   if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE))
106     if (bop->isAssignmentOp())
107       return bop->getRHS();
108   return 0;
109 }
110
111 QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
112   QualType resultTy;
113   bool isLVal = false;
114
115   if (CallE) {
116     isLVal = CallE->isLValue();
117     const Expr *Callee = CallE->getCallee();
118     if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
119       resultTy = FD->getResultType();
120     else
121       resultTy = CallE->getType();
122   }
123   else {
124     isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) &&
125              Msg.getOriginExpr()->isLValue();
126     resultTy = Msg.getResultType(ctx);
127   }
128
129   if (isLVal)
130     resultTy = ctx.getPointerType(resultTy);
131
132   return resultTy;
133 }
134
135 SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const {
136   assert(i < getNumArgs());
137   if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i));
138   QualType argT = Msg.getArgType(i);
139   if (Loc::isLocType(argT) || argT->isIntegerType())
140     return Msg.getArgSVal(i, State);
141   return UnknownVal();
142 }
143
144 SVal CallOrObjCMessage::getFunctionCallee() const {
145   assert(isFunctionCall());
146   assert(!isCXXCall());
147   const Expr *callee = CallE->getCallee()->IgnoreParenCasts();
148   return State->getSVal(callee);
149 }
150
151 SVal CallOrObjCMessage::getCXXCallee() const {
152   assert(isCXXCall());
153   const Expr *callee =
154     cast<CXXMemberCallExpr>(CallE)->getImplicitObjectArgument();
155   return State->getSVal(callee);  
156 }