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