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();
44 FirstCoroutineStmtLoc
= SourceLocation();
45 CoroutinePromise
= nullptr;
46 CoroutineParameterMoves
.clear();
47 NeedsCoroutineSuspends
= true;
48 CoroutineSuspends
.first
= nullptr;
49 CoroutineSuspends
.second
= nullptr;
54 PossiblyUnreachableDiags
.clear();
55 WeakObjectUses
.clear();
56 ModifiedNonNullParams
.clear();
58 ByrefBlockVars
.clear();
62 static const NamedDecl
*getBestPropertyDecl(const ObjCPropertyRefExpr
*PropE
) {
63 if (PropE
->isExplicitProperty())
64 return PropE
->getExplicitProperty();
66 return PropE
->getImplicitPropertyGetter();
69 FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
70 FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr
*E
) {
71 E
= E
->IgnoreParenCasts();
73 const NamedDecl
*D
= nullptr;
76 switch (E
->getStmtClass()) {
77 case Stmt::DeclRefExprClass
:
78 D
= cast
<DeclRefExpr
>(E
)->getDecl();
79 IsExact
= isa
<VarDecl
>(D
);
81 case Stmt::MemberExprClass
: {
82 const MemberExpr
*ME
= cast
<MemberExpr
>(E
);
83 D
= ME
->getMemberDecl();
84 IsExact
= isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts());
87 case Stmt::ObjCIvarRefExprClass
: {
88 const ObjCIvarRefExpr
*IE
= cast
<ObjCIvarRefExpr
>(E
);
90 IsExact
= IE
->getBase()->isObjCSelfExpr();
93 case Stmt::PseudoObjectExprClass
: {
94 const PseudoObjectExpr
*POE
= cast
<PseudoObjectExpr
>(E
);
95 const ObjCPropertyRefExpr
*BaseProp
=
96 dyn_cast
<ObjCPropertyRefExpr
>(POE
->getSyntacticForm());
98 D
= getBestPropertyDecl(BaseProp
);
100 if (BaseProp
->isObjectReceiver()) {
101 const Expr
*DoubleBase
= BaseProp
->getBase();
102 if (const OpaqueValueExpr
*OVE
= dyn_cast
<OpaqueValueExpr
>(DoubleBase
))
103 DoubleBase
= OVE
->getSourceExpr();
105 IsExact
= DoubleBase
->isObjCSelfExpr();
114 return BaseInfoTy(D
, IsExact
);
117 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
118 const ObjCPropertyRefExpr
*PropE
)
119 : Base(nullptr, true), Property(getBestPropertyDecl(PropE
)) {
121 if (PropE
->isObjectReceiver()) {
122 const OpaqueValueExpr
*OVE
= cast
<OpaqueValueExpr
>(PropE
->getBase());
123 const Expr
*E
= OVE
->getSourceExpr();
124 Base
= getBaseInfo(E
);
125 } else if (PropE
->isClassReceiver()) {
126 Base
.setPointer(PropE
->getClassReceiver());
128 assert(PropE
->isSuperReceiver());
132 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr
*BaseE
,
133 const ObjCPropertyDecl
*Prop
)
134 : Base(nullptr, true), Property(Prop
) {
136 Base
= getBaseInfo(BaseE
);
137 // else, this is a message accessing a property on super.
140 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
141 const DeclRefExpr
*DRE
)
142 : Base(nullptr, true), Property(DRE
->getDecl()) {
143 assert(isa
<VarDecl
>(Property
));
146 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
147 const ObjCIvarRefExpr
*IvarE
)
148 : Base(getBaseInfo(IvarE
->getBase())), Property(IvarE
->getDecl()) {
151 void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr
*Msg
,
152 const ObjCPropertyDecl
*Prop
) {
154 WeakUseVector
&Uses
=
155 WeakObjectUses
[WeakObjectProfileTy(Msg
->getInstanceReceiver(), Prop
)];
156 Uses
.push_back(WeakUseTy(Msg
, Msg
->getNumArgs() == 0));
159 void FunctionScopeInfo::markSafeWeakUse(const Expr
*E
) {
160 E
= E
->IgnoreParenCasts();
162 if (const PseudoObjectExpr
*POE
= dyn_cast
<PseudoObjectExpr
>(E
)) {
163 markSafeWeakUse(POE
->getSyntacticForm());
167 if (const ConditionalOperator
*Cond
= dyn_cast
<ConditionalOperator
>(E
)) {
168 markSafeWeakUse(Cond
->getTrueExpr());
169 markSafeWeakUse(Cond
->getFalseExpr());
173 if (const BinaryConditionalOperator
*Cond
=
174 dyn_cast
<BinaryConditionalOperator
>(E
)) {
175 markSafeWeakUse(Cond
->getCommon());
176 markSafeWeakUse(Cond
->getFalseExpr());
180 // Has this weak object been seen before?
181 FunctionScopeInfo::WeakObjectUseMap::iterator Uses
= WeakObjectUses
.end();
182 if (const ObjCPropertyRefExpr
*RefExpr
= dyn_cast
<ObjCPropertyRefExpr
>(E
)) {
183 if (!RefExpr
->isObjectReceiver())
185 if (isa
<OpaqueValueExpr
>(RefExpr
->getBase()))
186 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(RefExpr
));
188 markSafeWeakUse(RefExpr
->getBase());
192 else if (const ObjCIvarRefExpr
*IvarE
= dyn_cast
<ObjCIvarRefExpr
>(E
))
193 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(IvarE
));
194 else if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
195 if (isa
<VarDecl
>(DRE
->getDecl()))
196 Uses
= WeakObjectUses
.find(WeakObjectProfileTy(DRE
));
197 } else if (const ObjCMessageExpr
*MsgE
= dyn_cast
<ObjCMessageExpr
>(E
)) {
198 if (const ObjCMethodDecl
*MD
= MsgE
->getMethodDecl()) {
199 if (const ObjCPropertyDecl
*Prop
= MD
->findPropertyDecl()) {
201 WeakObjectUses
.find(WeakObjectProfileTy(MsgE
->getInstanceReceiver(),
209 if (Uses
== WeakObjectUses
.end())
212 // Has there been a read from the object using this Expr?
213 FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse
=
214 llvm::find(llvm::reverse(Uses
->second
), WeakUseTy(E
, true));
215 if (ThisUse
== Uses
->second
.rend())
221 bool Capture::isInitCapture() const {
222 // Note that a nested capture of an init-capture is not itself an
224 return !isNested() && isVariableCapture() && getVariable()->isInitCapture();
227 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType
*VAT
) const {
228 for (auto &Cap
: Captures
)
229 if (Cap
.isVLATypeCapture() && Cap
.getCapturedVLAType() == VAT
)
234 void LambdaScopeInfo::visitPotentialCaptures(
235 llvm::function_ref
<void(ValueDecl
*, Expr
*)> Callback
) const {
236 for (Expr
*E
: PotentiallyCapturingExprs
) {
237 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
238 Callback(cast
<ValueDecl
>(DRE
->getFoundDecl()), E
);
239 } else if (auto *ME
= dyn_cast
<MemberExpr
>(E
)) {
240 Callback(cast
<ValueDecl
>(ME
->getMemberDecl()), E
);
241 } else if (auto *FP
= dyn_cast
<FunctionParmPackExpr
>(E
)) {
242 for (ValueDecl
*VD
: *FP
)
245 llvm_unreachable("unexpected expression in potential captures list");
250 FunctionScopeInfo::~FunctionScopeInfo() { }
251 BlockScopeInfo::~BlockScopeInfo() { }
252 CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }