]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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 (isObjCMessage()) {
116     isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) &&
117              Msg.getOriginExpr()->isLValue();
118     resultTy = Msg.getResultType(ctx);
119   } else if (const CXXConstructExpr *Ctor =
120               CallE.dyn_cast<const CXXConstructExpr *>()) {
121     resultTy = Ctor->getType();
122   } else {
123     const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
124
125     isLVal = FunctionCall->isLValue();
126     const Expr *Callee = FunctionCall->getCallee();
127     if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
128       resultTy = FD->getResultType();
129     else
130       resultTy = FunctionCall->getType();
131   }
132
133   if (isLVal)
134     resultTy = ctx.getPointerType(resultTy);
135
136   return resultTy;
137 }
138
139 SVal CallOrObjCMessage::getFunctionCallee() const {
140   assert(isFunctionCall());
141   assert(!isCXXCall());
142   const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
143   return State->getSVal(Fun);
144 }
145
146 SVal CallOrObjCMessage::getCXXCallee() const {
147   assert(isCXXCall());
148   const CallExpr *ActualCall = CallE.get<const CallExpr *>();
149   const Expr *callee =
150     cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
151   
152   // FIXME: Will eventually need to cope with member pointers.  This is
153   // a limitation in getImplicitObjectArgument().
154   if (!callee)
155     return UnknownVal();
156   
157   return State->getSVal(callee);
158 }
159
160 SVal
161 CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
162   assert(isObjCMessage());
163   return Msg.getInstanceReceiverSVal(State, LC);
164 }