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
22using namespace clang;
23using namespace sema;
24
25void 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  FoundImmediateEscalatingExpression = false;
43
44  // Coroutine state
45  FirstCoroutineStmtLoc = SourceLocation();
46  CoroutinePromise = nullptr;
47  CoroutineParameterMoves.clear();
48  NeedsCoroutineSuspends = true;
49  CoroutineSuspends.first = nullptr;
50  CoroutineSuspends.second = nullptr;
51
52  SwitchStack.clear();
53  Returns.clear();
54  ErrorTrap.reset();
55  PossiblyUnreachableDiags.clear();
56  WeakObjectUses.clear();
57  ModifiedNonNullParams.clear();
58  Blocks.clear();
59  ByrefBlockVars.clear();
60  AddrLabels.clear();
61}
62
63static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
64  if (PropE->isExplicitProperty())
65    return PropE->getExplicitProperty();
66
67  return PropE->getImplicitPropertyGetter();
68}
69
70FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
71FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
72  E = E->IgnoreParenCasts();
73
74  const NamedDecl *D = nullptr;
75  bool IsExact = false;
76
77  switch (E->getStmtClass()) {
78  case Stmt::DeclRefExprClass:
79    D = cast<DeclRefExpr>(E)->getDecl();
80    IsExact = isa<VarDecl>(D);
81    break;
82  case Stmt::MemberExprClass: {
83    const MemberExpr *ME = cast<MemberExpr>(E);
84    D = ME->getMemberDecl();
85    IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
86    break;
87  }
88  case Stmt::ObjCIvarRefExprClass: {
89    const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
90    D = IE->getDecl();
91    IsExact = IE->getBase()->isObjCSelfExpr();
92    break;
93  }
94  case Stmt::PseudoObjectExprClass: {
95    const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
96    const ObjCPropertyRefExpr *BaseProp =
97      dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
98    if (BaseProp) {
99      D = getBestPropertyDecl(BaseProp);
100
101      if (BaseProp->isObjectReceiver()) {
102        const Expr *DoubleBase = BaseProp->getBase();
103        if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
104          DoubleBase = OVE->getSourceExpr();
105
106        IsExact = DoubleBase->isObjCSelfExpr();
107      }
108    }
109    break;
110  }
111  default:
112    break;
113  }
114
115  return BaseInfoTy(D, IsExact);
116}
117
118FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
119                                          const ObjCPropertyRefExpr *PropE)
120    : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
121
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());
128  } else {
129    assert(PropE->isSuperReceiver());
130  }
131}
132
133FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
134                                                const ObjCPropertyDecl *Prop)
135    : Base(nullptr, true), Property(Prop) {
136  if (BaseE)
137    Base = getBaseInfo(BaseE);
138  // else, this is a message accessing a property on super.
139}
140
141FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
142                                                      const DeclRefExpr *DRE)
143  : Base(nullptr, true), Property(DRE->getDecl()) {
144  assert(isa<VarDecl>(Property));
145}
146
147FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
148                                                  const ObjCIvarRefExpr *IvarE)
149  : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
150}
151
152void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
153                                        const ObjCPropertyDecl *Prop) {
154  assert(Msg && Prop);
155  WeakUseVector &Uses =
156    WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
157  Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
158}
159
160void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
161  E = E->IgnoreParenCasts();
162
163  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
164    markSafeWeakUse(POE->getSyntacticForm());
165    return;
166  }
167
168  if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
169    markSafeWeakUse(Cond->getTrueExpr());
170    markSafeWeakUse(Cond->getFalseExpr());
171    return;
172  }
173
174  if (const BinaryConditionalOperator *Cond =
175        dyn_cast<BinaryConditionalOperator>(E)) {
176    markSafeWeakUse(Cond->getCommon());
177    markSafeWeakUse(Cond->getFalseExpr());
178    return;
179  }
180
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())
185      return;
186    if (isa<OpaqueValueExpr>(RefExpr->getBase()))
187     Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
188    else {
189      markSafeWeakUse(RefExpr->getBase());
190      return;
191    }
192  }
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()) {
201        Uses =
202          WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
203                                                  Prop));
204      }
205    }
206  }
207  else
208    return;
209
210  if (Uses == WeakObjectUses.end())
211    return;
212
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())
217    return;
218
219  ThisUse->markSafe();
220}
221
222bool Capture::isInitCapture() const {
223  // Note that a nested capture of an init-capture is not itself an
224  // init-capture.
225  return !isNested() && isVariableCapture() && getVariable()->isInitCapture();
226}
227
228bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
229  for (auto &Cap : Captures)
230    if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT)
231      return true;
232  return false;
233}
234
235void 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)
244        Callback(VD, E);
245    } else {
246      llvm_unreachable("unexpected expression in potential captures list");
247    }
248  }
249}
250
251bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const {
252  if (ExplicitObjectParameter)
253    return ExplicitObjectParameter->getType()
254        .getNonReferenceType()
255        .isConstQualified();
256  return !Mutable;
257}
258
259FunctionScopeInfo::~FunctionScopeInfo() { }
260BlockScopeInfo::~BlockScopeInfo() { }
261CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
262