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