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