xref: /freebsd/contrib/llvm-project/clang/lib/Sema/ScopeInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===--- ScopeInfo.cpp - Information about a semantic context -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements FunctionScopeInfo and its subclasses, which contain
10 // information about a single function, block, lambda, or method body.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Sema/ScopeInfo.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclCXX.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 
22 using namespace clang;
23 using namespace sema;
24 
Clear()25 void FunctionScopeInfo::Clear() {
26   HasBranchProtectedScope = false;
27   HasBranchIntoScope = false;
28   HasIndirectGoto = false;
29   HasDroppedStmt = false;
30   HasOMPDeclareReductionCombiner = false;
31   HasFallthroughStmt = false;
32   UsesFPIntrin = false;
33   HasPotentialAvailabilityViolations = false;
34   ObjCShouldCallSuper = false;
35   ObjCIsDesignatedInit = false;
36   ObjCWarnForNoDesignatedInitChain = false;
37   ObjCIsSecondaryInit = false;
38   ObjCWarnForNoInitDelegation = false;
39   FirstReturnLoc = SourceLocation();
40   FirstCXXOrObjCTryLoc = SourceLocation();
41   FirstSEHTryLoc = SourceLocation();
42   FirstVLALoc = SourceLocation();
43   FoundImmediateEscalatingExpression = false;
44 
45   // Coroutine state
46   FirstCoroutineStmtLoc = SourceLocation();
47   CoroutinePromise = nullptr;
48   CoroutineParameterMoves.clear();
49   NeedsCoroutineSuspends = true;
50   CoroutineSuspends.first = nullptr;
51   CoroutineSuspends.second = nullptr;
52 
53   SwitchStack.clear();
54   Returns.clear();
55   ErrorTrap.reset();
56   PossiblyUnreachableDiags.clear();
57   WeakObjectUses.clear();
58   ModifiedNonNullParams.clear();
59   Blocks.clear();
60   ByrefBlockVars.clear();
61   AddrLabels.clear();
62 }
63 
getBestPropertyDecl(const ObjCPropertyRefExpr * PropE)64 static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
65   if (PropE->isExplicitProperty())
66     return PropE->getExplicitProperty();
67 
68   return PropE->getImplicitPropertyGetter();
69 }
70 
71 FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
getBaseInfo(const Expr * E)72 FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
73   E = E->IgnoreParenCasts();
74 
75   const NamedDecl *D = nullptr;
76   bool IsExact = false;
77 
78   switch (E->getStmtClass()) {
79   case Stmt::DeclRefExprClass:
80     D = cast<DeclRefExpr>(E)->getDecl();
81     IsExact = isa<VarDecl>(D);
82     break;
83   case Stmt::MemberExprClass: {
84     const MemberExpr *ME = cast<MemberExpr>(E);
85     D = ME->getMemberDecl();
86     IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
87     break;
88   }
89   case Stmt::ObjCIvarRefExprClass: {
90     const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
91     D = IE->getDecl();
92     IsExact = IE->getBase()->isObjCSelfExpr();
93     break;
94   }
95   case Stmt::PseudoObjectExprClass: {
96     const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
97     const ObjCPropertyRefExpr *BaseProp =
98       dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
99     if (BaseProp) {
100       D = getBestPropertyDecl(BaseProp);
101 
102       if (BaseProp->isObjectReceiver()) {
103         const Expr *DoubleBase = BaseProp->getBase();
104         if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
105           DoubleBase = OVE->getSourceExpr();
106 
107         IsExact = DoubleBase->isObjCSelfExpr();
108       }
109     }
110     break;
111   }
112   default:
113     break;
114   }
115 
116   return BaseInfoTy(D, IsExact);
117 }
118 
WeakObjectProfileTy(const ObjCPropertyRefExpr * PropE)119 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
120                                           const ObjCPropertyRefExpr *PropE)
121     : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
122 
123   if (PropE->isObjectReceiver()) {
124     const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
125     const Expr *E = OVE->getSourceExpr();
126     Base = getBaseInfo(E);
127   } else if (PropE->isClassReceiver()) {
128     Base.setPointer(PropE->getClassReceiver());
129   } else {
130     assert(PropE->isSuperReceiver());
131   }
132 }
133 
WeakObjectProfileTy(const Expr * BaseE,const ObjCPropertyDecl * Prop)134 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
135                                                 const ObjCPropertyDecl *Prop)
136     : Base(nullptr, true), Property(Prop) {
137   if (BaseE)
138     Base = getBaseInfo(BaseE);
139   // else, this is a message accessing a property on super.
140 }
141 
WeakObjectProfileTy(const DeclRefExpr * DRE)142 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
143                                                       const DeclRefExpr *DRE)
144   : Base(nullptr, true), Property(DRE->getDecl()) {
145   assert(isa<VarDecl>(Property));
146 }
147 
WeakObjectProfileTy(const ObjCIvarRefExpr * IvarE)148 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
149                                                   const ObjCIvarRefExpr *IvarE)
150   : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
151 }
152 
recordUseOfWeak(const ObjCMessageExpr * Msg,const ObjCPropertyDecl * Prop)153 void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
154                                         const ObjCPropertyDecl *Prop) {
155   assert(Msg && Prop);
156   WeakUseVector &Uses =
157     WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
158   Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
159 }
160 
markSafeWeakUse(const Expr * E)161 void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
162   E = E->IgnoreParenCasts();
163 
164   if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
165     markSafeWeakUse(POE->getSyntacticForm());
166     return;
167   }
168 
169   if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
170     markSafeWeakUse(Cond->getTrueExpr());
171     markSafeWeakUse(Cond->getFalseExpr());
172     return;
173   }
174 
175   if (const BinaryConditionalOperator *Cond =
176         dyn_cast<BinaryConditionalOperator>(E)) {
177     markSafeWeakUse(Cond->getCommon());
178     markSafeWeakUse(Cond->getFalseExpr());
179     return;
180   }
181 
182   // Has this weak object been seen before?
183   FunctionScopeInfo::WeakObjectUseMap::iterator Uses = WeakObjectUses.end();
184   if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
185     if (!RefExpr->isObjectReceiver())
186       return;
187     if (isa<OpaqueValueExpr>(RefExpr->getBase()))
188      Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
189     else {
190       markSafeWeakUse(RefExpr->getBase());
191       return;
192     }
193   }
194   else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
195     Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
196   else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
197     if (isa<VarDecl>(DRE->getDecl()))
198       Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
199   } else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
200     if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
201       if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
202         Uses =
203           WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
204                                                   Prop));
205       }
206     }
207   }
208   else
209     return;
210 
211   if (Uses == WeakObjectUses.end())
212     return;
213 
214   // Has there been a read from the object using this Expr?
215   FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
216       llvm::find(llvm::reverse(Uses->second), WeakUseTy(E, true));
217   if (ThisUse == Uses->second.rend())
218     return;
219 
220   ThisUse->markSafe();
221 }
222 
isInitCapture() const223 bool Capture::isInitCapture() const {
224   // Note that a nested capture of an init-capture is not itself an
225   // init-capture.
226   return !isNested() && isVariableCapture() && getVariable()->isInitCapture();
227 }
228 
isVLATypeCaptured(const VariableArrayType * VAT) const229 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
230   for (auto &Cap : Captures)
231     if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT)
232       return true;
233   return false;
234 }
235 
visitPotentialCaptures(llvm::function_ref<void (ValueDecl *,Expr *)> Callback) const236 void LambdaScopeInfo::visitPotentialCaptures(
237     llvm::function_ref<void(ValueDecl *, Expr *)> Callback) const {
238   for (Expr *E : PotentiallyCapturingExprs) {
239     if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
240       Callback(cast<ValueDecl>(DRE->getFoundDecl()), E);
241     } else if (auto *ME = dyn_cast<MemberExpr>(E)) {
242       Callback(cast<ValueDecl>(ME->getMemberDecl()), E);
243     } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) {
244       for (ValueDecl *VD : *FP)
245         Callback(VD, E);
246     } else {
247       llvm_unreachable("unexpected expression in potential captures list");
248     }
249   }
250 }
251 
lambdaCaptureShouldBeConst() const252 bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const {
253   if (ExplicitObjectParameter)
254     return ExplicitObjectParameter->getType()
255         .getNonReferenceType()
256         .isConstQualified();
257   return !Mutable;
258 }
259 
~FunctionScopeInfo()260 FunctionScopeInfo::~FunctionScopeInfo() { }
~BlockScopeInfo()261 BlockScopeInfo::~BlockScopeInfo() { }
~CapturedRegionScopeInfo()262 CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
263