ScopeInfo.cpp revision 263508
1//===--- ScopeInfo.cpp - Information about a semantic context -------------===//
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 implements FunctionScopeInfo and its subclasses, which contain
11// information about a single function, block, lambda, or method body.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Sema/ScopeInfo.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/ExprObjC.h"
21
22using namespace clang;
23using namespace sema;
24
25void FunctionScopeInfo::Clear() {
26  HasBranchProtectedScope = false;
27  HasBranchIntoScope = false;
28  HasIndirectGoto = false;
29
30  SwitchStack.clear();
31  Returns.clear();
32  ErrorTrap.reset();
33  PossiblyUnreachableDiags.clear();
34  WeakObjectUses.clear();
35}
36
37static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
38  if (PropE->isExplicitProperty())
39    return PropE->getExplicitProperty();
40
41  return PropE->getImplicitPropertyGetter();
42}
43
44FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
45FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
46  E = E->IgnoreParenCasts();
47
48  const NamedDecl *D = 0;
49  bool IsExact = false;
50
51  switch (E->getStmtClass()) {
52  case Stmt::DeclRefExprClass:
53    D = cast<DeclRefExpr>(E)->getDecl();
54    IsExact = isa<VarDecl>(D);
55    break;
56  case Stmt::MemberExprClass: {
57    const MemberExpr *ME = cast<MemberExpr>(E);
58    D = ME->getMemberDecl();
59    IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
60    break;
61  }
62  case Stmt::ObjCIvarRefExprClass: {
63    const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
64    D = IE->getDecl();
65    IsExact = IE->getBase()->isObjCSelfExpr();
66    break;
67  }
68  case Stmt::PseudoObjectExprClass: {
69    const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
70    const ObjCPropertyRefExpr *BaseProp =
71      dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
72    if (BaseProp) {
73      D = getBestPropertyDecl(BaseProp);
74
75      const Expr *DoubleBase = BaseProp->getBase();
76      if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
77        DoubleBase = OVE->getSourceExpr();
78
79      IsExact = DoubleBase->isObjCSelfExpr();
80    }
81    break;
82  }
83  default:
84    break;
85  }
86
87  return BaseInfoTy(D, IsExact);
88}
89
90
91FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
92                                          const ObjCPropertyRefExpr *PropE)
93    : Base(0, true), Property(getBestPropertyDecl(PropE)) {
94
95  if (PropE->isObjectReceiver()) {
96    const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
97    const Expr *E = OVE->getSourceExpr();
98    Base = getBaseInfo(E);
99  } else if (PropE->isClassReceiver()) {
100    Base.setPointer(PropE->getClassReceiver());
101  } else {
102    assert(PropE->isSuperReceiver());
103  }
104}
105
106FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
107                                                const ObjCPropertyDecl *Prop)
108    : Base(0, true), Property(Prop) {
109  if (BaseE)
110    Base = getBaseInfo(BaseE);
111  // else, this is a message accessing a property on super.
112}
113
114FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
115                                                      const DeclRefExpr *DRE)
116  : Base(0, true), Property(DRE->getDecl()) {
117  assert(isa<VarDecl>(Property));
118}
119
120FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
121                                                  const ObjCIvarRefExpr *IvarE)
122  : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
123}
124
125void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
126                                        const ObjCPropertyDecl *Prop) {
127  assert(Msg && Prop);
128  WeakUseVector &Uses =
129    WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
130  Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
131}
132
133void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
134  E = E->IgnoreParenCasts();
135
136  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
137    markSafeWeakUse(POE->getSyntacticForm());
138    return;
139  }
140
141  if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
142    markSafeWeakUse(Cond->getTrueExpr());
143    markSafeWeakUse(Cond->getFalseExpr());
144    return;
145  }
146
147  if (const BinaryConditionalOperator *Cond =
148        dyn_cast<BinaryConditionalOperator>(E)) {
149    markSafeWeakUse(Cond->getCommon());
150    markSafeWeakUse(Cond->getFalseExpr());
151    return;
152  }
153
154  // Has this weak object been seen before?
155  FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
156  if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E))
157    Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
158  else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
159    Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
160  else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
161    Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
162  else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
163    Uses = WeakObjectUses.end();
164    if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
165      if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
166        Uses =
167          WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
168                                                  Prop));
169      }
170    }
171  }
172  else
173    return;
174
175  if (Uses == WeakObjectUses.end())
176    return;
177
178  // Has there been a read from the object using this Expr?
179  FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
180    std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
181  if (ThisUse == Uses->second.rend())
182    return;
183
184  ThisUse->markSafe();
185}
186
187void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) {
188  assert(Idx < getNumPotentialVariableCaptures() &&
189    "Index of potential capture must be within 0 to less than the "
190    "number of captures!");
191  E = PotentiallyCapturingExprs[Idx];
192  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
193    VD = dyn_cast<VarDecl>(DRE->getFoundDecl());
194  else if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
195    VD = dyn_cast<VarDecl>(ME->getMemberDecl());
196  else
197    llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for "
198    "potential captures");
199  assert(VD);
200}
201
202FunctionScopeInfo::~FunctionScopeInfo() { }
203BlockScopeInfo::~BlockScopeInfo() { }
204LambdaScopeInfo::~LambdaScopeInfo() { }
205CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
206