/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Sema/ScopeInfo.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===// |
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 defines FunctionScopeInfo and its subclasses, which contain |
10 | | // information about a single function, block, lambda, or method body. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_SEMA_SCOPEINFO_H |
15 | | #define LLVM_CLANG_SEMA_SCOPEINFO_H |
16 | | |
17 | | #include "clang/AST/Expr.h" |
18 | | #include "clang/AST/ExprCXX.h" |
19 | | #include "clang/AST/Type.h" |
20 | | #include "clang/Basic/CapturedStmt.h" |
21 | | #include "clang/Basic/LLVM.h" |
22 | | #include "clang/Basic/PartialDiagnostic.h" |
23 | | #include "clang/Basic/SourceLocation.h" |
24 | | #include "clang/Sema/CleanupInfo.h" |
25 | | #include "clang/Sema/DeclSpec.h" |
26 | | #include "llvm/ADT/DenseMap.h" |
27 | | #include "llvm/ADT/DenseMapInfo.h" |
28 | | #include "llvm/ADT/MapVector.h" |
29 | | #include "llvm/ADT/PointerIntPair.h" |
30 | | #include "llvm/ADT/SmallPtrSet.h" |
31 | | #include "llvm/ADT/SmallSet.h" |
32 | | #include "llvm/ADT/SmallVector.h" |
33 | | #include "llvm/ADT/StringRef.h" |
34 | | #include "llvm/ADT/StringSwitch.h" |
35 | | #include "llvm/ADT/TinyPtrVector.h" |
36 | | #include "llvm/Support/Casting.h" |
37 | | #include "llvm/Support/ErrorHandling.h" |
38 | | #include <algorithm> |
39 | | #include <cassert> |
40 | | #include <utility> |
41 | | |
42 | | namespace clang { |
43 | | |
44 | | class BlockDecl; |
45 | | class CapturedDecl; |
46 | | class CXXMethodDecl; |
47 | | class CXXRecordDecl; |
48 | | class ImplicitParamDecl; |
49 | | class NamedDecl; |
50 | | class ObjCIvarRefExpr; |
51 | | class ObjCMessageExpr; |
52 | | class ObjCPropertyDecl; |
53 | | class ObjCPropertyRefExpr; |
54 | | class ParmVarDecl; |
55 | | class RecordDecl; |
56 | | class ReturnStmt; |
57 | | class Scope; |
58 | | class Stmt; |
59 | | class SwitchStmt; |
60 | | class TemplateParameterList; |
61 | | class VarDecl; |
62 | | |
63 | | namespace sema { |
64 | | |
65 | | /// Contains information about the compound statement currently being |
66 | | /// parsed. |
67 | | class CompoundScopeInfo { |
68 | | public: |
69 | | /// Whether this compound stamement contains `for' or `while' loops |
70 | | /// with empty bodies. |
71 | | bool HasEmptyLoopBodies = false; |
72 | | |
73 | | /// Whether this compound statement corresponds to a GNU statement |
74 | | /// expression. |
75 | | bool IsStmtExpr; |
76 | | |
77 | 4.38M | CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {} |
78 | | |
79 | 23.1k | void setHasEmptyLoopBodies() { |
80 | 23.1k | HasEmptyLoopBodies = true; |
81 | 23.1k | } |
82 | | }; |
83 | | |
84 | | class PossiblyUnreachableDiag { |
85 | | public: |
86 | | PartialDiagnostic PD; |
87 | | SourceLocation Loc; |
88 | | llvm::TinyPtrVector<const Stmt*> Stmts; |
89 | | |
90 | | PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, |
91 | | ArrayRef<const Stmt *> Stmts) |
92 | 39.2k | : PD(PD), Loc(Loc), Stmts(Stmts) {} |
93 | | }; |
94 | | |
95 | | /// Retains information about a function, method, or block that is |
96 | | /// currently being parsed. |
97 | | class FunctionScopeInfo { |
98 | | protected: |
99 | | enum ScopeKind { |
100 | | SK_Function, |
101 | | SK_Block, |
102 | | SK_Lambda, |
103 | | SK_CapturedRegion |
104 | | }; |
105 | | |
106 | | public: |
107 | | /// What kind of scope we are describing. |
108 | | ScopeKind Kind : 3; |
109 | | |
110 | | /// Whether this function contains a VLA, \@try, try, C++ |
111 | | /// initializer, or anything else that can't be jumped past. |
112 | | bool HasBranchProtectedScope : 1; |
113 | | |
114 | | /// Whether this function contains any switches or direct gotos. |
115 | | bool HasBranchIntoScope : 1; |
116 | | |
117 | | /// Whether this function contains any indirect gotos. |
118 | | bool HasIndirectGoto : 1; |
119 | | |
120 | | /// Whether this function contains any statement marked with |
121 | | /// \c [[clang::musttail]]. |
122 | | bool HasMustTail : 1; |
123 | | |
124 | | /// Whether a statement was dropped because it was invalid. |
125 | | bool HasDroppedStmt : 1; |
126 | | |
127 | | /// True if current scope is for OpenMP declare reduction combiner. |
128 | | bool HasOMPDeclareReductionCombiner : 1; |
129 | | |
130 | | /// Whether there is a fallthrough statement in this function. |
131 | | bool HasFallthroughStmt : 1; |
132 | | |
133 | | /// Whether this function uses constrained floating point intrinsics |
134 | | bool UsesFPIntrin : 1; |
135 | | |
136 | | /// Whether we make reference to a declaration that could be |
137 | | /// unavailable. |
138 | | bool HasPotentialAvailabilityViolations : 1; |
139 | | |
140 | | /// A flag that is set when parsing a method that must call super's |
141 | | /// implementation, such as \c -dealloc, \c -finalize, or any method marked |
142 | | /// with \c __attribute__((objc_requires_super)). |
143 | | bool ObjCShouldCallSuper : 1; |
144 | | |
145 | | /// True when this is a method marked as a designated initializer. |
146 | | bool ObjCIsDesignatedInit : 1; |
147 | | |
148 | | /// This starts true for a method marked as designated initializer and will |
149 | | /// be set to false if there is an invocation to a designated initializer of |
150 | | /// the super class. |
151 | | bool ObjCWarnForNoDesignatedInitChain : 1; |
152 | | |
153 | | /// True when this is an initializer method not marked as a designated |
154 | | /// initializer within a class that has at least one initializer marked as a |
155 | | /// designated initializer. |
156 | | bool ObjCIsSecondaryInit : 1; |
157 | | |
158 | | /// This starts true for a secondary initializer method and will be set to |
159 | | /// false if there is an invocation of an initializer on 'self'. |
160 | | bool ObjCWarnForNoInitDelegation : 1; |
161 | | |
162 | | /// True only when this function has not already built, or attempted |
163 | | /// to build, the initial and final coroutine suspend points |
164 | | bool NeedsCoroutineSuspends : 1; |
165 | | |
166 | | /// An enumeration represeting the kind of the first coroutine statement |
167 | | /// in the function. One of co_return, co_await, or co_yield. |
168 | | unsigned char FirstCoroutineStmtKind : 2; |
169 | | |
170 | | /// First coroutine statement in the current function. |
171 | | /// (ex co_return, co_await, co_yield) |
172 | | SourceLocation FirstCoroutineStmtLoc; |
173 | | |
174 | | /// First 'return' statement in the current function. |
175 | | SourceLocation FirstReturnLoc; |
176 | | |
177 | | /// First C++ 'try' or ObjC @try statement in the current function. |
178 | | SourceLocation FirstCXXOrObjCTryLoc; |
179 | | enum { TryLocIsCXX, TryLocIsObjC, Unknown } FirstTryType = Unknown; |
180 | | |
181 | | /// First SEH '__try' statement in the current function. |
182 | | SourceLocation FirstSEHTryLoc; |
183 | | |
184 | | private: |
185 | | /// Used to determine if errors occurred in this function or block. |
186 | | DiagnosticErrorTrap ErrorTrap; |
187 | | |
188 | | public: |
189 | | /// A SwitchStmt, along with a flag indicating if its list of case statements |
190 | | /// is incomplete (because we dropped an invalid one while parsing). |
191 | | using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>; |
192 | | |
193 | | /// SwitchStack - This is the current set of active switch statements in the |
194 | | /// block. |
195 | | SmallVector<SwitchInfo, 8> SwitchStack; |
196 | | |
197 | | /// The list of return statements that occur within the function or |
198 | | /// block, if there is any chance of applying the named return value |
199 | | /// optimization, or if we need to infer a return type. |
200 | | SmallVector<ReturnStmt*, 4> Returns; |
201 | | |
202 | | /// The promise object for this coroutine, if any. |
203 | | VarDecl *CoroutinePromise = nullptr; |
204 | | |
205 | | /// A mapping between the coroutine function parameters that were moved |
206 | | /// to the coroutine frame, and their move statements. |
207 | | llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves; |
208 | | |
209 | | /// The initial and final coroutine suspend points. |
210 | | std::pair<Stmt *, Stmt *> CoroutineSuspends; |
211 | | |
212 | | /// The stack of currently active compound stamement scopes in the |
213 | | /// function. |
214 | | SmallVector<CompoundScopeInfo, 4> CompoundScopes; |
215 | | |
216 | | /// The set of blocks that are introduced in this function. |
217 | | llvm::SmallPtrSet<const BlockDecl *, 1> Blocks; |
218 | | |
219 | | /// The set of __block variables that are introduced in this function. |
220 | | llvm::TinyPtrVector<VarDecl *> ByrefBlockVars; |
221 | | |
222 | | /// A list of PartialDiagnostics created but delayed within the |
223 | | /// current function scope. These diagnostics are vetted for reachability |
224 | | /// prior to being emitted. |
225 | | SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; |
226 | | |
227 | | /// A list of parameters which have the nonnull attribute and are |
228 | | /// modified in the function. |
229 | | llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams; |
230 | | |
231 | | public: |
232 | | /// Represents a simple identification of a weak object. |
233 | | /// |
234 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
235 | | /// |
236 | | /// This is used to determine if two weak accesses refer to the same object. |
237 | | /// Here are some examples of how various accesses are "profiled": |
238 | | /// |
239 | | /// Access Expression | "Base" Decl | "Property" Decl |
240 | | /// :---------------: | :-----------------: | :------------------------------: |
241 | | /// self.property | self (VarDecl) | property (ObjCPropertyDecl) |
242 | | /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl) |
243 | | /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl) |
244 | | /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl) |
245 | | /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl) |
246 | | /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl) |
247 | | /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl) |
248 | | /// MyClass.foo.prop | +foo (ObjCMethodDecl) | -prop (ObjCPropertyDecl) |
249 | | /// weakVar | 0 (known) | weakVar (VarDecl) |
250 | | /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl) |
251 | | /// |
252 | | /// Objects are identified with only two Decls to make it reasonably fast to |
253 | | /// compare them. |
254 | | class WeakObjectProfileTy { |
255 | | /// The base object decl, as described in the class documentation. |
256 | | /// |
257 | | /// The extra flag is "true" if the Base and Property are enough to uniquely |
258 | | /// identify the object in memory. |
259 | | /// |
260 | | /// \sa isExactProfile() |
261 | | using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>; |
262 | | BaseInfoTy Base; |
263 | | |
264 | | /// The "property" decl, as described in the class documentation. |
265 | | /// |
266 | | /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the |
267 | | /// case of "implicit" properties (regular methods accessed via dot syntax). |
268 | | const NamedDecl *Property = nullptr; |
269 | | |
270 | | /// Used to find the proper base profile for a given base expression. |
271 | | static BaseInfoTy getBaseInfo(const Expr *BaseE); |
272 | | |
273 | | inline WeakObjectProfileTy(); |
274 | | static inline WeakObjectProfileTy getSentinel(); |
275 | | |
276 | | public: |
277 | | WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); |
278 | | WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); |
279 | | WeakObjectProfileTy(const DeclRefExpr *RE); |
280 | | WeakObjectProfileTy(const ObjCIvarRefExpr *RE); |
281 | | |
282 | 18 | const NamedDecl *getBase() const { return Base.getPointer(); } |
283 | 84 | const NamedDecl *getProperty() const { return Property; } |
284 | | |
285 | | /// Returns true if the object base specifies a known object in memory, |
286 | | /// rather than, say, an instance variable or property of another object. |
287 | | /// |
288 | | /// Note that this ignores the effects of aliasing; that is, \c foo.bar is |
289 | | /// considered an exact profile if \c foo is a local variable, even if |
290 | | /// another variable \c foo2 refers to the same object as \c foo. |
291 | | /// |
292 | | /// For increased precision, accesses with base variables that are |
293 | | /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to |
294 | | /// be exact, though this is not true for arbitrary variables |
295 | | /// (foo.prop1.prop2). |
296 | 102 | bool isExactProfile() const { |
297 | 102 | return Base.getInt(); |
298 | 102 | } |
299 | | |
300 | 6.50M | bool operator==(const WeakObjectProfileTy &Other) const { |
301 | 6.50M | return Base == Other.Base && Property == Other.Property6.50M ; |
302 | 6.50M | } |
303 | | |
304 | | // For use in DenseMap. |
305 | | // We can't specialize the usual llvm::DenseMapInfo at the end of the file |
306 | | // because by that point the DenseMap in FunctionScopeInfo has already been |
307 | | // instantiated. |
308 | | class DenseMapInfo { |
309 | | public: |
310 | 1.68M | static inline WeakObjectProfileTy getEmptyKey() { |
311 | 1.68M | return WeakObjectProfileTy(); |
312 | 1.68M | } |
313 | | |
314 | 802k | static inline WeakObjectProfileTy getTombstoneKey() { |
315 | 802k | return WeakObjectProfileTy::getSentinel(); |
316 | 802k | } |
317 | | |
318 | 346 | static unsigned getHashValue(const WeakObjectProfileTy &Val) { |
319 | 346 | using Pair = std::pair<BaseInfoTy, const NamedDecl *>; |
320 | | |
321 | 346 | return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base, |
322 | 346 | Val.Property)); |
323 | 346 | } |
324 | | |
325 | | static bool isEqual(const WeakObjectProfileTy &LHS, |
326 | 6.50M | const WeakObjectProfileTy &RHS) { |
327 | 6.50M | return LHS == RHS; |
328 | 6.50M | } |
329 | | }; |
330 | | }; |
331 | | |
332 | | /// Represents a single use of a weak object. |
333 | | /// |
334 | | /// Stores both the expression and whether the access is potentially unsafe |
335 | | /// (i.e. it could potentially be warned about). |
336 | | /// |
337 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
338 | | class WeakUseTy { |
339 | | llvm::PointerIntPair<const Expr *, 1, bool> Rep; |
340 | | |
341 | | public: |
342 | 326 | WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} |
343 | | |
344 | 487 | const Expr *getUseExpr() const { return Rep.getPointer(); } |
345 | 271 | bool isUnsafe() const { return Rep.getInt(); } |
346 | 44 | void markSafe() { Rep.setInt(false); } |
347 | | |
348 | 50 | bool operator==(const WeakUseTy &Other) const { |
349 | 50 | return Rep == Other.Rep; |
350 | 50 | } |
351 | | }; |
352 | | |
353 | | /// Used to collect uses of a particular weak object in a function body. |
354 | | /// |
355 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
356 | | using WeakUseVector = SmallVector<WeakUseTy, 4>; |
357 | | |
358 | | /// Used to collect all uses of weak objects in a function body. |
359 | | /// |
360 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
361 | | using WeakObjectUseMap = |
362 | | llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, |
363 | | WeakObjectProfileTy::DenseMapInfo>; |
364 | | |
365 | | private: |
366 | | /// Used to collect all uses of weak objects in this function body. |
367 | | /// |
368 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
369 | | WeakObjectUseMap WeakObjectUses; |
370 | | |
371 | | protected: |
372 | 10.6k | FunctionScopeInfo(const FunctionScopeInfo&) = default; |
373 | | |
374 | | public: |
375 | | FunctionScopeInfo(DiagnosticsEngine &Diag) |
376 | | : Kind(SK_Function), HasBranchProtectedScope(false), |
377 | | HasBranchIntoScope(false), HasIndirectGoto(false), HasMustTail(false), |
378 | | HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), |
379 | | HasFallthroughStmt(false), UsesFPIntrin(false), |
380 | | HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false), |
381 | | ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), |
382 | | ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), |
383 | 784k | NeedsCoroutineSuspends(true), ErrorTrap(Diag) {} |
384 | | |
385 | | virtual ~FunctionScopeInfo(); |
386 | | |
387 | | /// Determine whether an unrecoverable error has occurred within this |
388 | | /// function. Note that this may return false even if the function body is |
389 | | /// invalid, because the errors may be suppressed if they're caused by prior |
390 | | /// invalid declarations. |
391 | | /// |
392 | | /// FIXME: Migrate the caller of this to use containsErrors() instead once |
393 | | /// it's ready. |
394 | 15.2k | bool hasUnrecoverableErrorOccurred() const { |
395 | 15.2k | return ErrorTrap.hasUnrecoverableErrorOccurred(); |
396 | 15.2k | } |
397 | | |
398 | | /// Record that a weak object was accessed. |
399 | | /// |
400 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
401 | | template <typename ExprT> |
402 | | inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); |
403 | | |
404 | | void recordUseOfWeak(const ObjCMessageExpr *Msg, |
405 | | const ObjCPropertyDecl *Prop); |
406 | | |
407 | | /// Record that a given expression is a "safe" access of a weak object (e.g. |
408 | | /// assigning it to a strong variable.) |
409 | | /// |
410 | | /// Part of the implementation of -Wrepeated-use-of-weak. |
411 | | void markSafeWeakUse(const Expr *E); |
412 | | |
413 | 112 | const WeakObjectUseMap &getWeakObjectUses() const { |
414 | 112 | return WeakObjectUses; |
415 | 112 | } |
416 | | |
417 | 9.07k | void setHasBranchIntoScope() { |
418 | 9.07k | HasBranchIntoScope = true; |
419 | 9.07k | } |
420 | | |
421 | 1.52M | void setHasBranchProtectedScope() { |
422 | 1.52M | HasBranchProtectedScope = true; |
423 | 1.52M | } |
424 | | |
425 | 130 | void setHasIndirectGoto() { |
426 | 130 | HasIndirectGoto = true; |
427 | 130 | } |
428 | | |
429 | 70 | void setHasMustTail() { HasMustTail = true; } |
430 | | |
431 | 0 | void setHasDroppedStmt() { |
432 | 0 | HasDroppedStmt = true; |
433 | 0 | } |
434 | | |
435 | 766 | void setHasOMPDeclareReductionCombiner() { |
436 | 766 | HasOMPDeclareReductionCombiner = true; |
437 | 766 | } |
438 | | |
439 | 1.03k | void setHasFallthroughStmt() { |
440 | 1.03k | HasFallthroughStmt = true; |
441 | 1.03k | } |
442 | | |
443 | 102k | void setUsesFPIntrin() { |
444 | 102k | UsesFPIntrin = true; |
445 | 102k | } |
446 | | |
447 | 12.0k | void setHasCXXTry(SourceLocation TryLoc) { |
448 | 12.0k | setHasBranchProtectedScope(); |
449 | 12.0k | FirstCXXOrObjCTryLoc = TryLoc; |
450 | 12.0k | FirstTryType = TryLocIsCXX; |
451 | 12.0k | } |
452 | | |
453 | 309 | void setHasObjCTry(SourceLocation TryLoc) { |
454 | 309 | setHasBranchProtectedScope(); |
455 | 309 | FirstCXXOrObjCTryLoc = TryLoc; |
456 | 309 | FirstTryType = TryLocIsObjC; |
457 | 309 | } |
458 | | |
459 | 280 | void setHasSEHTry(SourceLocation TryLoc) { |
460 | 280 | setHasBranchProtectedScope(); |
461 | 280 | FirstSEHTryLoc = TryLoc; |
462 | 280 | } |
463 | | |
464 | 3.60M | bool NeedsScopeChecking() const { |
465 | 3.60M | return !HasDroppedStmt && (HasIndirectGoto || HasMustTail3.60M || |
466 | 3.60M | (3.60M HasBranchProtectedScope3.60M && HasBranchIntoScope222k )); |
467 | 3.60M | } |
468 | | |
469 | | // Add a block introduced in this function. |
470 | 3.11k | void addBlock(const BlockDecl *BD) { |
471 | 3.11k | Blocks.insert(BD); |
472 | 3.11k | } |
473 | | |
474 | | // Add a __block variable introduced in this function. |
475 | 498 | void addByrefBlockVar(VarDecl *VD) { |
476 | 498 | ByrefBlockVars.push_back(VD); |
477 | 498 | } |
478 | | |
479 | 537k | bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); } |
480 | | |
481 | 1.14k | void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) { |
482 | 1.14k | assert(FirstCoroutineStmtLoc.isInvalid() && |
483 | 1.14k | "first coroutine statement location already set"); |
484 | 0 | FirstCoroutineStmtLoc = Loc; |
485 | 1.14k | FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword) |
486 | 1.14k | .Case("co_return", 0) |
487 | 1.14k | .Case("co_await", 1) |
488 | 1.14k | .Case("co_yield", 2); |
489 | 1.14k | } |
490 | | |
491 | 92 | StringRef getFirstCoroutineStmtKeyword() const { |
492 | 92 | assert(FirstCoroutineStmtLoc.isValid() |
493 | 92 | && "no coroutine statement available"); |
494 | 0 | switch (FirstCoroutineStmtKind) { |
495 | 47 | case 0: return "co_return"; |
496 | 20 | case 1: return "co_await"; |
497 | 25 | case 2: return "co_yield"; |
498 | 0 | default: |
499 | 0 | llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); |
500 | 92 | }; |
501 | 0 | } |
502 | | |
503 | 1.07k | void setNeedsCoroutineSuspends(bool value = true) { |
504 | 1.07k | assert((!value || CoroutineSuspends.first == nullptr) && |
505 | 1.07k | "we already have valid suspend points"); |
506 | 0 | NeedsCoroutineSuspends = value; |
507 | 1.07k | } |
508 | | |
509 | 1.04k | bool hasInvalidCoroutineSuspends() const { |
510 | 1.04k | return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr; |
511 | 1.04k | } |
512 | | |
513 | 1.02k | void setCoroutineSuspends(Stmt *Initial, Stmt *Final) { |
514 | 1.02k | assert(Initial && Final && "suspend points cannot be null"); |
515 | 0 | assert(CoroutineSuspends.first == nullptr && "suspend points already set"); |
516 | 0 | NeedsCoroutineSuspends = false; |
517 | 1.02k | CoroutineSuspends.first = Initial; |
518 | 1.02k | CoroutineSuspends.second = Final; |
519 | 1.02k | } |
520 | | |
521 | | /// Clear out the information in this function scope, making it |
522 | | /// suitable for reuse. |
523 | | void Clear(); |
524 | | |
525 | 4.27M | bool isPlainFunction() const { return Kind == SK_Function; } |
526 | | }; |
527 | | |
528 | | class Capture { |
529 | | // There are three categories of capture: capturing 'this', capturing |
530 | | // local variables, and C++1y initialized captures (which can have an |
531 | | // arbitrary initializer, and don't really capture in the traditional |
532 | | // sense at all). |
533 | | // |
534 | | // There are three ways to capture a local variable: |
535 | | // - capture by copy in the C++11 sense, |
536 | | // - capture by reference in the C++11 sense, and |
537 | | // - __block capture. |
538 | | // Lambdas explicitly specify capture by copy or capture by reference. |
539 | | // For blocks, __block capture applies to variables with that annotation, |
540 | | // variables of reference type are captured by reference, and other |
541 | | // variables are captured by copy. |
542 | | enum CaptureKind { |
543 | | Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA |
544 | | }; |
545 | | |
546 | | union { |
547 | | /// If Kind == Cap_VLA, the captured type. |
548 | | const VariableArrayType *CapturedVLA; |
549 | | |
550 | | /// Otherwise, the captured variable (if any). |
551 | | VarDecl *CapturedVar; |
552 | | }; |
553 | | |
554 | | /// The source location at which the first capture occurred. |
555 | | SourceLocation Loc; |
556 | | |
557 | | /// The location of the ellipsis that expands a parameter pack. |
558 | | SourceLocation EllipsisLoc; |
559 | | |
560 | | /// The type as it was captured, which is the type of the non-static data |
561 | | /// member that would hold the capture. |
562 | | QualType CaptureType; |
563 | | |
564 | | /// The CaptureKind of this capture. |
565 | | unsigned Kind : 2; |
566 | | |
567 | | /// Whether this is a nested capture (a capture of an enclosing capturing |
568 | | /// scope's capture). |
569 | | unsigned Nested : 1; |
570 | | |
571 | | /// Whether this is a capture of '*this'. |
572 | | unsigned CapturesThis : 1; |
573 | | |
574 | | /// Whether an explicit capture has been odr-used in the body of the |
575 | | /// lambda. |
576 | | unsigned ODRUsed : 1; |
577 | | |
578 | | /// Whether an explicit capture has been non-odr-used in the body of |
579 | | /// the lambda. |
580 | | unsigned NonODRUsed : 1; |
581 | | |
582 | | /// Whether the capture is invalid (a capture was required but the entity is |
583 | | /// non-capturable). |
584 | | unsigned Invalid : 1; |
585 | | |
586 | | public: |
587 | | Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, |
588 | | SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType, |
589 | | bool Invalid) |
590 | | : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc), |
591 | | CaptureType(CaptureType), |
592 | | Kind(Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy), |
593 | | Nested(IsNested), CapturesThis(false), ODRUsed(false), |
594 | 410k | NonODRUsed(false), Invalid(Invalid) {} |
595 | | |
596 | | enum IsThisCapture { ThisCapture }; |
597 | | Capture(IsThisCapture, bool IsNested, SourceLocation Loc, |
598 | | QualType CaptureType, const bool ByCopy, bool Invalid) |
599 | | : Loc(Loc), CaptureType(CaptureType), |
600 | | Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested), |
601 | | CapturesThis(true), ODRUsed(false), NonODRUsed(false), |
602 | 11.5k | Invalid(Invalid) {} |
603 | | |
604 | | enum IsVLACapture { VLACapture }; |
605 | | Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested, |
606 | | SourceLocation Loc, QualType CaptureType) |
607 | | : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA), |
608 | | Nested(IsNested), CapturesThis(false), ODRUsed(false), |
609 | 8.94k | NonODRUsed(false), Invalid(false) {} |
610 | | |
611 | 3.75M | bool isThisCapture() const { return CapturesThis; } |
612 | 2.96M | bool isVariableCapture() const { |
613 | 2.96M | return !isThisCapture() && !isVLATypeCapture()2.94M ; |
614 | 2.96M | } |
615 | | |
616 | 997k | bool isCopyCapture() const { return Kind == Cap_ByCopy; } |
617 | 374k | bool isReferenceCapture() const { return Kind == Cap_ByRef; } |
618 | 9.18k | bool isBlockCapture() const { return Kind == Cap_Block; } |
619 | 4.25M | bool isVLATypeCapture() const { return Kind == Cap_VLA; } |
620 | | |
621 | 394k | bool isNested() const { return Nested; } |
622 | | |
623 | 403k | bool isInvalid() const { return Invalid; } |
624 | | |
625 | | /// Determine whether this capture is an init-capture. |
626 | | bool isInitCapture() const; |
627 | | |
628 | 1.57k | bool isODRUsed() const { return ODRUsed; } |
629 | 640 | bool isNonODRUsed() const { return NonODRUsed; } |
630 | 986k | void markUsed(bool IsODRUse) { |
631 | 986k | if (IsODRUse) |
632 | 355k | ODRUsed = true; |
633 | 631k | else |
634 | 631k | NonODRUsed = true; |
635 | 986k | } |
636 | | |
637 | 1.65M | VarDecl *getVariable() const { |
638 | 1.65M | assert(isVariableCapture()); |
639 | 0 | return CapturedVar; |
640 | 1.65M | } |
641 | | |
642 | 40.0k | const VariableArrayType *getCapturedVLAType() const { |
643 | 40.0k | assert(isVLATypeCapture()); |
644 | 0 | return CapturedVLA; |
645 | 40.0k | } |
646 | | |
647 | | /// Retrieve the location at which this variable was captured. |
648 | 1.19M | SourceLocation getLocation() const { return Loc; } |
649 | | |
650 | | /// Retrieve the source location of the ellipsis, whose presence |
651 | | /// indicates that the capture is a pack expansion. |
652 | 5.09k | SourceLocation getEllipsisLoc() const { return EllipsisLoc; } |
653 | | |
654 | | /// Retrieve the capture type for this capture, which is effectively |
655 | | /// the type of the non-static data member in the lambda/block structure |
656 | | /// that would store this capture. |
657 | 1.38M | QualType getCaptureType() const { return CaptureType; } |
658 | | }; |
659 | | |
660 | | class CapturingScopeInfo : public FunctionScopeInfo { |
661 | | protected: |
662 | 10.6k | CapturingScopeInfo(const CapturingScopeInfo&) = default; |
663 | | |
664 | | public: |
665 | | enum ImplicitCaptureStyle { |
666 | | ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, |
667 | | ImpCap_CapturedRegion |
668 | | }; |
669 | | |
670 | | ImplicitCaptureStyle ImpCaptureStyle; |
671 | | |
672 | | CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) |
673 | 588k | : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {} |
674 | | |
675 | | /// CaptureMap - A map of captured variables to (index+1) into Captures. |
676 | | llvm::DenseMap<VarDecl*, unsigned> CaptureMap; |
677 | | |
678 | | /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; |
679 | | /// zero if 'this' is not captured. |
680 | | unsigned CXXThisCaptureIndex = 0; |
681 | | |
682 | | /// Captures - The captures. |
683 | | SmallVector<Capture, 4> Captures; |
684 | | |
685 | | /// - Whether the target type of return statements in this context |
686 | | /// is deduced (e.g. a lambda or block with omitted return type). |
687 | | bool HasImplicitReturnType = false; |
688 | | |
689 | | /// ReturnType - The target type of return statements in this context, |
690 | | /// or null if unknown. |
691 | | QualType ReturnType; |
692 | | |
693 | | void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, |
694 | | SourceLocation Loc, SourceLocation EllipsisLoc, |
695 | 410k | QualType CaptureType, bool Invalid) { |
696 | 410k | Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, |
697 | 410k | EllipsisLoc, CaptureType, Invalid)); |
698 | 410k | CaptureMap[Var] = Captures.size(); |
699 | 410k | } |
700 | | |
701 | | void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType, |
702 | 8.94k | QualType CaptureType) { |
703 | 8.94k | Captures.push_back(Capture(Capture::VLACapture, VLAType, |
704 | 8.94k | /*FIXME: IsNested*/ false, Loc, CaptureType)); |
705 | 8.94k | } |
706 | | |
707 | | void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, |
708 | | bool ByCopy); |
709 | | |
710 | | /// Determine whether the C++ 'this' is captured. |
711 | 7.88k | bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } |
712 | | |
713 | | /// Retrieve the capture of C++ 'this', if it has been captured. |
714 | 2.59k | Capture &getCXXThisCapture() { |
715 | 2.59k | assert(isCXXThisCaptured() && "this has not been captured"); |
716 | 0 | return Captures[CXXThisCaptureIndex - 1]; |
717 | 2.59k | } |
718 | | |
719 | | /// Determine whether the given variable has been captured. |
720 | 2.92M | bool isCaptured(VarDecl *Var) const { |
721 | 2.92M | return CaptureMap.count(Var); |
722 | 2.92M | } |
723 | | |
724 | | /// Determine whether the given variable-array type has been captured. |
725 | | bool isVLATypeCaptured(const VariableArrayType *VAT) const; |
726 | | |
727 | | /// Retrieve the capture of the given variable, if it has been |
728 | | /// captured already. |
729 | 2.92M | Capture &getCapture(VarDecl *Var) { |
730 | 2.92M | assert(isCaptured(Var) && "Variable has not been captured"); |
731 | 0 | return Captures[CaptureMap[Var] - 1]; |
732 | 2.92M | } |
733 | | |
734 | 0 | const Capture &getCapture(VarDecl *Var) const { |
735 | 0 | llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known |
736 | 0 | = CaptureMap.find(Var); |
737 | 0 | assert(Known != CaptureMap.end() && "Variable has not been captured"); |
738 | 0 | return Captures[Known->second - 1]; |
739 | 0 | } |
740 | | |
741 | 19.0M | static bool classof(const FunctionScopeInfo *FSI) { |
742 | 19.0M | return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda19.0M |
743 | 19.0M | || FSI->Kind == SK_CapturedRegion18.9M ; |
744 | 19.0M | } |
745 | | }; |
746 | | |
747 | | /// Retains information about a block that is currently being parsed. |
748 | | class BlockScopeInfo final : public CapturingScopeInfo { |
749 | | public: |
750 | | BlockDecl *TheDecl; |
751 | | |
752 | | /// TheScope - This is the scope for the block itself, which contains |
753 | | /// arguments etc. |
754 | | Scope *TheScope; |
755 | | |
756 | | /// BlockType - The function type of the block, if one was given. |
757 | | /// Its return type may be BuiltinType::Dependent. |
758 | | QualType FunctionType; |
759 | | |
760 | | BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) |
761 | | : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), |
762 | 3.38k | TheScope(BlockScope) { |
763 | 3.38k | Kind = SK_Block; |
764 | 3.38k | } |
765 | | |
766 | | ~BlockScopeInfo() override; |
767 | | |
768 | 2.98M | static bool classof(const FunctionScopeInfo *FSI) { |
769 | 2.98M | return FSI->Kind == SK_Block; |
770 | 2.98M | } |
771 | | }; |
772 | | |
773 | | /// Retains information about a captured region. |
774 | | class CapturedRegionScopeInfo final : public CapturingScopeInfo { |
775 | | public: |
776 | | /// The CapturedDecl for this statement. |
777 | | CapturedDecl *TheCapturedDecl; |
778 | | |
779 | | /// The captured record type. |
780 | | RecordDecl *TheRecordDecl; |
781 | | |
782 | | /// This is the enclosing scope of the captured region. |
783 | | Scope *TheScope; |
784 | | |
785 | | /// The implicit parameter for the captured variables. |
786 | | ImplicitParamDecl *ContextParam; |
787 | | |
788 | | /// The kind of captured region. |
789 | | unsigned short CapRegionKind; |
790 | | |
791 | | unsigned short OpenMPLevel; |
792 | | unsigned short OpenMPCaptureLevel; |
793 | | |
794 | | CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD, |
795 | | RecordDecl *RD, ImplicitParamDecl *Context, |
796 | | CapturedRegionKind K, unsigned OpenMPLevel, |
797 | | unsigned OpenMPCaptureLevel) |
798 | | : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), |
799 | | TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), |
800 | | ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel), |
801 | 572k | OpenMPCaptureLevel(OpenMPCaptureLevel) { |
802 | 572k | Kind = SK_CapturedRegion; |
803 | 572k | } |
804 | | |
805 | | ~CapturedRegionScopeInfo() override; |
806 | | |
807 | | /// A descriptive name for the kind of captured region this is. |
808 | 241 | StringRef getRegionName() const { |
809 | 241 | switch (CapRegionKind) { |
810 | 1 | case CR_Default: |
811 | 1 | return "default captured statement"; |
812 | 0 | case CR_ObjCAtFinally: |
813 | 0 | return "Objective-C @finally statement"; |
814 | 240 | case CR_OpenMP: |
815 | 240 | return "OpenMP region"; |
816 | 241 | } |
817 | 0 | llvm_unreachable("Invalid captured region kind!"); |
818 | 0 | } |
819 | | |
820 | 4.15M | static bool classof(const FunctionScopeInfo *FSI) { |
821 | 4.15M | return FSI->Kind == SK_CapturedRegion; |
822 | 4.15M | } |
823 | | }; |
824 | | |
825 | | class LambdaScopeInfo final : |
826 | | public CapturingScopeInfo, public InventedTemplateParameterInfo { |
827 | | public: |
828 | | /// The class that describes the lambda. |
829 | | CXXRecordDecl *Lambda = nullptr; |
830 | | |
831 | | /// The lambda's compiler-generated \c operator(). |
832 | | CXXMethodDecl *CallOperator = nullptr; |
833 | | |
834 | | /// Source range covering the lambda introducer [...]. |
835 | | SourceRange IntroducerRange; |
836 | | |
837 | | /// Source location of the '&' or '=' specifying the default capture |
838 | | /// type, if any. |
839 | | SourceLocation CaptureDefaultLoc; |
840 | | |
841 | | /// The number of captures in the \c Captures list that are |
842 | | /// explicit captures. |
843 | | unsigned NumExplicitCaptures = 0; |
844 | | |
845 | | /// Whether this is a mutable lambda. |
846 | | bool Mutable = false; |
847 | | |
848 | | /// Whether the (empty) parameter list is explicit. |
849 | | bool ExplicitParams = false; |
850 | | |
851 | | /// Whether any of the capture expressions requires cleanups. |
852 | | CleanupInfo Cleanup; |
853 | | |
854 | | /// Whether the lambda contains an unexpanded parameter pack. |
855 | | bool ContainsUnexpandedParameterPack = false; |
856 | | |
857 | | /// Packs introduced by this lambda, if any. |
858 | | SmallVector<NamedDecl*, 4> LocalPacks; |
859 | | |
860 | | /// Source range covering the explicit template parameter list (if it exists). |
861 | | SourceRange ExplicitTemplateParamsRange; |
862 | | |
863 | | /// The requires-clause immediately following the explicit template parameter |
864 | | /// list, if any. (Note that there may be another requires-clause included as |
865 | | /// part of the lambda-declarator.) |
866 | | ExprResult RequiresClause; |
867 | | |
868 | | /// If this is a generic lambda, and the template parameter |
869 | | /// list has been created (from the TemplateParams) then store |
870 | | /// a reference to it (cache it to avoid reconstructing it). |
871 | | TemplateParameterList *GLTemplateParameterList = nullptr; |
872 | | |
873 | | /// Contains all variable-referring-expressions (i.e. DeclRefExprs |
874 | | /// or MemberExprs) that refer to local variables in a generic lambda |
875 | | /// or a lambda in a potentially-evaluated-if-used context. |
876 | | /// |
877 | | /// Potentially capturable variables of a nested lambda that might need |
878 | | /// to be captured by the lambda are housed here. |
879 | | /// This is specifically useful for generic lambdas or |
880 | | /// lambdas within a potentially evaluated-if-used context. |
881 | | /// If an enclosing variable is named in an expression of a lambda nested |
882 | | /// within a generic lambda, we don't always know know whether the variable |
883 | | /// will truly be odr-used (i.e. need to be captured) by that nested lambda, |
884 | | /// until its instantiation. But we still need to capture it in the |
885 | | /// enclosing lambda if all intervening lambdas can capture the variable. |
886 | | llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs; |
887 | | |
888 | | /// Contains all variable-referring-expressions that refer |
889 | | /// to local variables that are usable as constant expressions and |
890 | | /// do not involve an odr-use (they may still need to be captured |
891 | | /// if the enclosing full-expression is instantiation dependent). |
892 | | llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs; |
893 | | |
894 | | /// A map of explicit capture indices to their introducer source ranges. |
895 | | llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges; |
896 | | |
897 | | /// Contains all of the variables defined in this lambda that shadow variables |
898 | | /// that were defined in parent contexts. Used to avoid warnings when the |
899 | | /// shadowed variables are uncaptured by this lambda. |
900 | | struct ShadowedOuterDecl { |
901 | | const VarDecl *VD; |
902 | | const VarDecl *ShadowedDecl; |
903 | | }; |
904 | | llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls; |
905 | | |
906 | | SourceLocation PotentialThisCaptureLocation; |
907 | | |
908 | | LambdaScopeInfo(DiagnosticsEngine &Diag) |
909 | 13.4k | : CapturingScopeInfo(Diag, ImpCap_None) { |
910 | 13.4k | Kind = SK_Lambda; |
911 | 13.4k | } |
912 | | |
913 | | /// Note when all explicit captures have been added. |
914 | 10.8k | void finishedExplicitCaptures() { |
915 | 10.8k | NumExplicitCaptures = Captures.size(); |
916 | 10.8k | } |
917 | | |
918 | 16.4M | static bool classof(const FunctionScopeInfo *FSI) { |
919 | 16.4M | return FSI->Kind == SK_Lambda; |
920 | 16.4M | } |
921 | | |
922 | | /// Is this scope known to be for a generic lambda? (This will be false until |
923 | | /// we parse a template parameter list or the first 'auto'-typed parameter). |
924 | 0 | bool isGenericLambda() const { |
925 | 0 | return !TemplateParams.empty() || GLTemplateParameterList; |
926 | 0 | } |
927 | | |
928 | | /// Add a variable that might potentially be captured by the |
929 | | /// lambda and therefore the enclosing lambdas. |
930 | | /// |
931 | | /// This is also used by enclosing lambda's to speculatively capture |
932 | | /// variables that nested lambda's - depending on their enclosing |
933 | | /// specialization - might need to capture. |
934 | | /// Consider: |
935 | | /// void f(int, int); <-- don't capture |
936 | | /// void f(const int&, double); <-- capture |
937 | | /// void foo() { |
938 | | /// const int x = 10; |
939 | | /// auto L = [=](auto a) { // capture 'x' |
940 | | /// return [=](auto b) { |
941 | | /// f(x, a); // we may or may not need to capture 'x' |
942 | | /// }; |
943 | | /// }; |
944 | | /// } |
945 | 944 | void addPotentialCapture(Expr *VarExpr) { |
946 | 944 | assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr) || |
947 | 944 | isa<FunctionParmPackExpr>(VarExpr)); |
948 | 0 | PotentiallyCapturingExprs.push_back(VarExpr); |
949 | 944 | } |
950 | | |
951 | 76 | void addPotentialThisCapture(SourceLocation Loc) { |
952 | 76 | PotentialThisCaptureLocation = Loc; |
953 | 76 | } |
954 | | |
955 | 835 | bool hasPotentialThisCapture() const { |
956 | 835 | return PotentialThisCaptureLocation.isValid(); |
957 | 835 | } |
958 | | |
959 | | /// Mark a variable's reference in a lambda as non-odr using. |
960 | | /// |
961 | | /// For generic lambdas, if a variable is named in a potentially evaluated |
962 | | /// expression, where the enclosing full expression is dependent then we |
963 | | /// must capture the variable (given a default capture). |
964 | | /// This is accomplished by recording all references to variables |
965 | | /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of |
966 | | /// PotentialCaptures. All such variables have to be captured by that lambda, |
967 | | /// except for as described below. |
968 | | /// If that variable is usable as a constant expression and is named in a |
969 | | /// manner that does not involve its odr-use (e.g. undergoes |
970 | | /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the |
971 | | /// act of analyzing the enclosing full expression (ActOnFinishFullExpr) |
972 | | /// if we can determine that the full expression is not instantiation- |
973 | | /// dependent, then we can entirely avoid its capture. |
974 | | /// |
975 | | /// const int n = 0; |
976 | | /// [&] (auto x) { |
977 | | /// (void)+n + x; |
978 | | /// }; |
979 | | /// Interestingly, this strategy would involve a capture of n, even though |
980 | | /// it's obviously not odr-used here, because the full-expression is |
981 | | /// instantiation-dependent. It could be useful to avoid capturing such |
982 | | /// variables, even when they are referred to in an instantiation-dependent |
983 | | /// expression, if we can unambiguously determine that they shall never be |
984 | | /// odr-used. This would involve removal of the variable-referring-expression |
985 | | /// from the array of PotentialCaptures during the lvalue-to-rvalue |
986 | | /// conversions. But per the working draft N3797, (post-chicago 2013) we must |
987 | | /// capture such variables. |
988 | | /// Before anyone is tempted to implement a strategy for not-capturing 'n', |
989 | | /// consider the insightful warning in: |
990 | | /// /cfe-commits/Week-of-Mon-20131104/092596.html |
991 | | /// "The problem is that the set of captures for a lambda is part of the ABI |
992 | | /// (since lambda layout can be made visible through inline functions and the |
993 | | /// like), and there are no guarantees as to which cases we'll manage to build |
994 | | /// an lvalue-to-rvalue conversion in, when parsing a template -- some |
995 | | /// seemingly harmless change elsewhere in Sema could cause us to start or stop |
996 | | /// building such a node. So we need a rule that anyone can implement and get |
997 | | /// exactly the same result". |
998 | 471 | void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { |
999 | 471 | assert(isa<DeclRefExpr>(CapturingVarExpr) || |
1000 | 471 | isa<MemberExpr>(CapturingVarExpr) || |
1001 | 471 | isa<FunctionParmPackExpr>(CapturingVarExpr)); |
1002 | 0 | NonODRUsedCapturingExprs.insert(CapturingVarExpr); |
1003 | 471 | } |
1004 | 966 | bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const { |
1005 | 966 | assert(isa<DeclRefExpr>(CapturingVarExpr) || |
1006 | 966 | isa<MemberExpr>(CapturingVarExpr) || |
1007 | 966 | isa<FunctionParmPackExpr>(CapturingVarExpr)); |
1008 | 0 | return NonODRUsedCapturingExprs.count(CapturingVarExpr); |
1009 | 966 | } |
1010 | 0 | void removePotentialCapture(Expr *E) { |
1011 | 0 | llvm::erase_value(PotentiallyCapturingExprs, E); |
1012 | 0 | } |
1013 | 835 | void clearPotentialCaptures() { |
1014 | 835 | PotentiallyCapturingExprs.clear(); |
1015 | 835 | PotentialThisCaptureLocation = SourceLocation(); |
1016 | 835 | } |
1017 | 33.1k | unsigned getNumPotentialVariableCaptures() const { |
1018 | 33.1k | return PotentiallyCapturingExprs.size(); |
1019 | 33.1k | } |
1020 | | |
1021 | 33.1k | bool hasPotentialCaptures() const { |
1022 | 33.1k | return getNumPotentialVariableCaptures() || |
1023 | 33.1k | PotentialThisCaptureLocation.isValid()32.4k ; |
1024 | 33.1k | } |
1025 | | |
1026 | | void visitPotentialCaptures( |
1027 | | llvm::function_ref<void(VarDecl *, Expr *)> Callback) const; |
1028 | | }; |
1029 | | |
1030 | | FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() |
1031 | 2.48M | : Base(nullptr, false) {} |
1032 | | |
1033 | | FunctionScopeInfo::WeakObjectProfileTy |
1034 | 802k | FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { |
1035 | 802k | FunctionScopeInfo::WeakObjectProfileTy Result; |
1036 | 802k | Result.Base.setInt(true); |
1037 | 802k | return Result; |
1038 | 802k | } |
1039 | | |
1040 | | template <typename ExprT> |
1041 | 256 | void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { |
1042 | 256 | assert(E); |
1043 | 0 | WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; |
1044 | 256 | Uses.push_back(WeakUseTy(E, IsRead)); |
1045 | 256 | } void clang::sema::FunctionScopeInfo::recordUseOfWeak<clang::DeclRefExpr>(clang::DeclRefExpr const*, bool) Line | Count | Source | 1041 | 26 | void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { | 1042 | 26 | assert(E); | 1043 | 0 | WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; | 1044 | 26 | Uses.push_back(WeakUseTy(E, IsRead)); | 1045 | 26 | } |
void clang::sema::FunctionScopeInfo::recordUseOfWeak<clang::ObjCIvarRefExpr>(clang::ObjCIvarRefExpr const*, bool) Line | Count | Source | 1041 | 24 | void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { | 1042 | 24 | assert(E); | 1043 | 0 | WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; | 1044 | 24 | Uses.push_back(WeakUseTy(E, IsRead)); | 1045 | 24 | } |
void clang::sema::FunctionScopeInfo::recordUseOfWeak<clang::ObjCPropertyRefExpr>(clang::ObjCPropertyRefExpr const*, bool) Line | Count | Source | 1041 | 206 | void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { | 1042 | 206 | assert(E); | 1043 | 0 | WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; | 1044 | 206 | Uses.push_back(WeakUseTy(E, IsRead)); | 1045 | 206 | } |
|
1046 | | |
1047 | | inline void CapturingScopeInfo::addThisCapture(bool isNested, |
1048 | | SourceLocation Loc, |
1049 | | QualType CaptureType, |
1050 | 11.5k | bool ByCopy) { |
1051 | 11.5k | Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType, |
1052 | 11.5k | ByCopy, /*Invalid*/ false)); |
1053 | 11.5k | CXXThisCaptureIndex = Captures.size(); |
1054 | 11.5k | } |
1055 | | |
1056 | | } // namespace sema |
1057 | | |
1058 | | } // namespace clang |
1059 | | |
1060 | | #endif // LLVM_CLANG_SEMA_SCOPEINFO_H |