]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
MFC r234353:
[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 #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