1 //===--- ScopeInfo.cpp - Information about a semantic context -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements FunctionScopeInfo and its subclasses, which contain
10 // information about a single function, block, lambda, or method body.
12 //===----------------------------------------------------------------------===//
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"
22 using namespace clang
;
25 void FunctionScopeInfo::Clear() {
26 HasBranchProtectedScope
= false;
27 HasBranchIntoScope
= false;
28 HasIndirectGoto
= false;
29 HasDroppedStmt
= false;
30 HasOMPDeclareReductionCombiner
= false;
31 HasFallthroughStmt
= 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 FoundImmediateEscalatingExpression
= false;
45 FirstCoroutineStmtLoc
= SourceLocation();
46 CoroutinePromise
= nullptr;
47 CoroutineParameterMoves
.clear();
48 NeedsCoroutineSuspends
= true;
49 CoroutineSuspends
.first
= nullptr;
50 CoroutineSuspends
.second
= nullptr;
55 PossiblyUnreachableDiags
.clear();
56 WeakObjectUses
.clear();
57 ModifiedNonNullParams
.clear();
59 ByrefBlockVars
.clear();
63 static const NamedDecl
*getBestPropertyDecl(const ObjCPropertyRefExpr
*PropE
) {
64 if (PropE
->isExplicitProperty())
65 return PropE
->getExplicitProperty();
67 return PropE
->getImplicitPropertyGetter();
70 FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
71 FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr
*E
) {
72 E
= E
->IgnoreParenCasts();
74 const NamedDecl
*D
= nullptr;
77 switch (E
->getStmtClass()) {
78 case Stmt::DeclRefExprClass
:
79 D
= cast
<DeclRefExpr
>(E
)->getDecl();
80 IsExact
= isa
<VarDecl
>(D
);
82 case Stmt::MemberExprClass
: {
83 const MemberExpr
*ME
= cast
<MemberExpr
>(E
);
84 D
= ME
->getMemberDecl();
85 IsExact
= isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts());
88 case Stmt::ObjCIvarRefExprClass
: {
89 const ObjCIvarRefExpr
*IE
= cast
<ObjCIvarRefExpr
>(E
);
91 IsExact
= IE
->getBase()->isObjCSelfExpr();
94 case Stmt::PseudoObjectExprClass
: {
95 const PseudoObjectExpr
*POE
= cast
<PseudoObjectExpr
>(E
);
96 const ObjCPropertyRefExpr
*BaseProp
=
97 dyn_cast
<ObjCPropertyRefExpr
>(POE
->getSyntacticForm());
99 D
= getBestPropertyDecl(BaseProp
);
101 if (BaseProp
->isObjectReceiver()) {
102 const Expr
*DoubleBase
= BaseProp
->getBase();
103 if (const OpaqueValueExpr
*OVE
= dyn_cast
<OpaqueValueExpr
>(DoubleBase
))
104 DoubleBase
= OVE
->getSourceExpr();
106 IsExact
= DoubleBase
->isObjCSelfExpr();
115 return BaseInfoTy(D
, IsExact
);
118 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
119 const ObjCPropertyRefExpr
*PropE
)
120 : Base(nullptr, true), Property(getBestPropertyDecl(PropE
)) {
122 if (PropE
->isObjectReceiver()) {
123 const OpaqueValueExpr
*OVE
= cast
<OpaqueValueExpr
>(PropE
->getBase());
124 const Expr
*E
= OVE
->getSourceExpr();
125 Base
= getBaseInfo(E
);
126 } else if (PropE
->isClassReceiver()) {
127 Base
.setPointer(PropE
->getClassReceiver());
129 assert(PropE
->isSuperReceiver());
133 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr
*BaseE
,
134 const ObjCPropertyDecl
*Prop
)
135 : Base(nullptr, true), Property(Prop
) {
137 Base
= getBaseInfo(BaseE
);
138 // else, this is a message accessing a property on super.
141 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
142 const DeclRefExpr
*DRE
)
143 : Base(nullptr, true), Property(DRE
->getDecl()) {
144 assert(isa
<VarDecl
>(Property
));
147 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
148 const ObjCIvarRefExpr
*IvarE
)
149 : Base(getBaseInfo(IvarE
->getBase())), Property(IvarE
->getDecl()) {
152 void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr
*Msg
,
153 const ObjCPropertyDecl
*Prop
) {
155 WeakUseVector
&Uses
=
156 WeakObjectUses
[WeakObjectProfileTy(Msg
->getInstanceReceiver(), Prop
)];
157 Uses
.push_back(WeakUseTy(Msg
, Msg
->getNumArgs() == 0));
160 void FunctionScopeInfo::markSafeWeakUse(const Expr
*E
) {
161 E
= E
->IgnoreParenCasts();
163 if (const PseudoObjectExpr
*POE
= dyn_cast
<PseudoObjectExpr
>(E
)) {
164 markSafeWeakUse(POE
->getSyntacticForm());
168 if (const ConditionalOperator
*Cond
= dyn_cast
<ConditionalOperator
>(E
)) {
169 markSafeWeakUse(Cond
->getTrueExpr());
170 markSafeWeakUse(Cond
->getFalseExpr());
174 if (const BinaryConditionalOperator
*Cond
=
175 dyn_cast
<BinaryConditionalOperator
>(E
)) {
176 markSafeWeakUse(Cond
->getCommon());
177 markSafeWeakUse(Cond
->getFalseExpr());
181 // Has this weak object been seen before?
182 FunctionScopeInfo::WeakObjectUseMap::iterator Uses
= WeakObjectUses
.end();
183 if (const ObjCPropertyRefExpr
*RefExpr
= dyn_cast
<ObjCPropertyRefExpr
>(E
)) {
184 if (!RefExpr
->isObjectReceiver())
186 if (isa
<OpaqueValueExpr
>(RefExpr
->getBase()))
187 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(RefExpr
));
189 markSafeWeakUse(RefExpr
->getBase());
193 else if (const ObjCIvarRefExpr
*IvarE
= dyn_cast
<ObjCIvarRefExpr
>(E
))
194 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(IvarE
));
195 else if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
196 if (isa
<VarDecl
>(DRE
->getDecl()))
197 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(DRE
));
198 } else if (const ObjCMessageExpr
*MsgE
= dyn_cast
<ObjCMessageExpr
>(E
)) {
199 if (const ObjCMethodDecl
*MD
= MsgE
->getMethodDecl()) {
200 if (const ObjCPropertyDecl
*Prop
= MD
->findPropertyDecl()) {
202 WeakObjectUses
.find(WeakObjectProfileTy(MsgE
->getInstanceReceiver(),
210 if (Uses
== WeakObjectUses
.end())
213 // Has there been a read from the object using this Expr?
214 FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse
=
215 llvm::find(llvm::reverse(Uses
->second
), WeakUseTy(E
, true));
216 if (ThisUse
== Uses
->second
.rend())
222 bool Capture::isInitCapture() const {
223 // Note that a nested capture of an init-capture is not itself an
225 return !isNested() && isVariableCapture() && getVariable()->isInitCapture();
228 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType
*VAT
) const {
229 for (auto &Cap
: Captures
)
230 if (Cap
.isVLATypeCapture() && Cap
.getCapturedVLAType() == VAT
)
235 void LambdaScopeInfo::visitPotentialCaptures(
236 llvm::function_ref
<void(ValueDecl
*, Expr
*)> Callback
) const {
237 for (Expr
*E
: PotentiallyCapturingExprs
) {
238 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
239 Callback(cast
<ValueDecl
>(DRE
->getFoundDecl()), E
);
240 } else if (auto *ME
= dyn_cast
<MemberExpr
>(E
)) {
241 Callback(cast
<ValueDecl
>(ME
->getMemberDecl()), E
);
242 } else if (auto *FP
= dyn_cast
<FunctionParmPackExpr
>(E
)) {
243 for (ValueDecl
*VD
: *FP
)
246 llvm_unreachable("unexpected expression in potential captures list");
251 bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const {
252 if (ExplicitObjectParameter
)
253 return ExplicitObjectParameter
->getType()
254 .getNonReferenceType()
259 FunctionScopeInfo::~FunctionScopeInfo() { }
260 BlockScopeInfo::~BlockScopeInfo() { }
261 CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }