Coverage Report

Created: 2024-01-17 10:31

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