1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
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/Type.h" |
19 | #include "clang/Basic/CapturedStmt.h" |
20 | #include "clang/Basic/LLVM.h" |
21 | #include "clang/Basic/PartialDiagnostic.h" |
22 | #include "clang/Basic/SourceLocation.h" |
23 | #include "clang/Sema/CleanupInfo.h" |
24 | #include "llvm/ADT/DenseMap.h" |
25 | #include "llvm/ADT/DenseMapInfo.h" |
26 | #include "llvm/ADT/MapVector.h" |
27 | #include "llvm/ADT/PointerIntPair.h" |
28 | #include "llvm/ADT/SmallPtrSet.h" |
29 | #include "llvm/ADT/SmallSet.h" |
30 | #include "llvm/ADT/SmallVector.h" |
31 | #include "llvm/ADT/StringRef.h" |
32 | #include "llvm/ADT/StringSwitch.h" |
33 | #include "llvm/ADT/TinyPtrVector.h" |
34 | #include "llvm/Support/Casting.h" |
35 | #include "llvm/Support/ErrorHandling.h" |
36 | #include <algorithm> |
37 | #include <cassert> |
38 | #include <utility> |
39 | |
40 | namespace clang { |
41 | |
42 | class BlockDecl; |
43 | class CapturedDecl; |
44 | class CXXMethodDecl; |
45 | class CXXRecordDecl; |
46 | class ImplicitParamDecl; |
47 | class NamedDecl; |
48 | class ObjCIvarRefExpr; |
49 | class ObjCMessageExpr; |
50 | class ObjCPropertyDecl; |
51 | class ObjCPropertyRefExpr; |
52 | class ParmVarDecl; |
53 | class RecordDecl; |
54 | class ReturnStmt; |
55 | class Scope; |
56 | class Stmt; |
57 | class SwitchStmt; |
58 | class TemplateParameterList; |
59 | class TemplateTypeParmDecl; |
60 | class VarDecl; |
61 | |
62 | namespace sema { |
63 | |
64 | |
65 | |
66 | class CompoundScopeInfo { |
67 | public: |
68 | |
69 | |
70 | bool HasEmptyLoopBodies = false; |
71 | |
72 | |
73 | |
74 | bool IsStmtExpr; |
75 | |
76 | CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {} |
77 | |
78 | void setHasEmptyLoopBodies() { |
79 | HasEmptyLoopBodies = true; |
80 | } |
81 | }; |
82 | |
83 | class PossiblyUnreachableDiag { |
84 | public: |
85 | PartialDiagnostic PD; |
86 | SourceLocation Loc; |
87 | const Stmt *stmt; |
88 | |
89 | PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, |
90 | const Stmt *stmt) |
91 | : PD(PD), Loc(Loc), stmt(stmt) {} |
92 | }; |
93 | |
94 | |
95 | |
96 | class FunctionScopeInfo { |
97 | protected: |
98 | enum ScopeKind { |
99 | SK_Function, |
100 | SK_Block, |
101 | SK_Lambda, |
102 | SK_CapturedRegion |
103 | }; |
104 | |
105 | public: |
106 | |
107 | ScopeKind Kind : 3; |
108 | |
109 | |
110 | |
111 | bool HasBranchProtectedScope : 1; |
112 | |
113 | |
114 | bool HasBranchIntoScope : 1; |
115 | |
116 | |
117 | bool HasIndirectGoto : 1; |
118 | |
119 | |
120 | bool HasDroppedStmt : 1; |
121 | |
122 | |
123 | bool HasOMPDeclareReductionCombiner : 1; |
124 | |
125 | |
126 | bool HasFallthroughStmt : 1; |
127 | |
128 | |
129 | |
130 | bool HasPotentialAvailabilityViolations : 1; |
131 | |
132 | |
133 | |
134 | |
135 | bool ObjCShouldCallSuper : 1; |
136 | |
137 | |
138 | bool ObjCIsDesignatedInit : 1; |
139 | |
140 | |
141 | |
142 | |
143 | bool ObjCWarnForNoDesignatedInitChain : 1; |
144 | |
145 | |
146 | |
147 | |
148 | bool ObjCIsSecondaryInit : 1; |
149 | |
150 | |
151 | |
152 | bool ObjCWarnForNoInitDelegation : 1; |
153 | |
154 | |
155 | |
156 | bool NeedsCoroutineSuspends : 1; |
157 | |
158 | |
159 | |
160 | unsigned char FirstCoroutineStmtKind : 2; |
161 | |
162 | |
163 | |
164 | SourceLocation FirstCoroutineStmtLoc; |
165 | |
166 | |
167 | SourceLocation FirstReturnLoc; |
168 | |
169 | |
170 | SourceLocation FirstCXXTryLoc; |
171 | |
172 | |
173 | SourceLocation FirstSEHTryLoc; |
174 | |
175 | |
176 | DiagnosticErrorTrap ErrorTrap; |
177 | |
178 | |
179 | |
180 | using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>; |
181 | |
182 | |
183 | |
184 | SmallVector<SwitchInfo, 8> SwitchStack; |
185 | |
186 | |
187 | |
188 | |
189 | SmallVector<ReturnStmt*, 4> Returns; |
190 | |
191 | |
192 | VarDecl *CoroutinePromise = nullptr; |
193 | |
194 | |
195 | |
196 | llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves; |
197 | |
198 | |
199 | std::pair<Stmt *, Stmt *> CoroutineSuspends; |
200 | |
201 | |
202 | |
203 | SmallVector<CompoundScopeInfo, 4> CompoundScopes; |
204 | |
205 | |
206 | llvm::SmallPtrSet<const BlockDecl *, 1> Blocks; |
207 | |
208 | |
209 | llvm::TinyPtrVector<VarDecl *> ByrefBlockVars; |
210 | |
211 | |
212 | |
213 | |
214 | SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; |
215 | |
216 | |
217 | |
218 | llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams; |
219 | |
220 | public: |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | class WeakObjectProfileTy { |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>; |
251 | BaseInfoTy Base; |
252 | |
253 | |
254 | |
255 | |
256 | |
257 | const NamedDecl *Property = nullptr; |
258 | |
259 | |
260 | static BaseInfoTy getBaseInfo(const Expr *BaseE); |
261 | |
262 | inline WeakObjectProfileTy(); |
263 | static inline WeakObjectProfileTy getSentinel(); |
264 | |
265 | public: |
266 | WeakObjectProfileTy(const ObjCPropertyRefExpr *RE); |
267 | WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property); |
268 | WeakObjectProfileTy(const DeclRefExpr *RE); |
269 | WeakObjectProfileTy(const ObjCIvarRefExpr *RE); |
270 | |
271 | const NamedDecl *getBase() const { return Base.getPointer(); } |
272 | const NamedDecl *getProperty() const { return Property; } |
273 | |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 | |
283 | |
284 | |
285 | bool isExactProfile() const { |
286 | return Base.getInt(); |
287 | } |
288 | |
289 | bool operator==(const WeakObjectProfileTy &Other) const { |
290 | return Base == Other.Base && Property == Other.Property; |
291 | } |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | class DenseMapInfo { |
298 | public: |
299 | static inline WeakObjectProfileTy getEmptyKey() { |
300 | return WeakObjectProfileTy(); |
301 | } |
302 | |
303 | static inline WeakObjectProfileTy getTombstoneKey() { |
304 | return WeakObjectProfileTy::getSentinel(); |
305 | } |
306 | |
307 | static unsigned getHashValue(const WeakObjectProfileTy &Val) { |
308 | using Pair = std::pair<BaseInfoTy, const NamedDecl *>; |
309 | |
310 | return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base, |
311 | Val.Property)); |
312 | } |
313 | |
314 | static bool isEqual(const WeakObjectProfileTy &LHS, |
315 | const WeakObjectProfileTy &RHS) { |
316 | return LHS == RHS; |
317 | } |
318 | }; |
319 | }; |
320 | |
321 | |
322 | |
323 | |
324 | |
325 | |
326 | |
327 | class WeakUseTy { |
328 | llvm::PointerIntPair<const Expr *, 1, bool> Rep; |
329 | |
330 | public: |
331 | WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} |
332 | |
333 | const Expr *getUseExpr() const { return Rep.getPointer(); } |
334 | bool isUnsafe() const { return Rep.getInt(); } |
335 | void markSafe() { Rep.setInt(false); } |
336 | |
337 | bool operator==(const WeakUseTy &Other) const { |
338 | return Rep == Other.Rep; |
339 | } |
340 | }; |
341 | |
342 | |
343 | |
344 | |
345 | using WeakUseVector = SmallVector<WeakUseTy, 4>; |
346 | |
347 | |
348 | |
349 | |
350 | using WeakObjectUseMap = |
351 | llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, |
352 | WeakObjectProfileTy::DenseMapInfo>; |
353 | |
354 | private: |
355 | |
356 | |
357 | |
358 | WeakObjectUseMap WeakObjectUses; |
359 | |
360 | protected: |
361 | FunctionScopeInfo(const FunctionScopeInfo&) = default; |
362 | |
363 | public: |
364 | FunctionScopeInfo(DiagnosticsEngine &Diag) |
365 | : Kind(SK_Function), HasBranchProtectedScope(false), |
366 | HasBranchIntoScope(false), HasIndirectGoto(false), |
367 | HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), |
368 | HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false), |
369 | ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), |
370 | ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), |
371 | ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true), |
372 | ErrorTrap(Diag) {} |
373 | |
374 | virtual ~FunctionScopeInfo(); |
375 | |
376 | |
377 | |
378 | |
379 | template <typename ExprT> |
380 | inline void recordUseOfWeak(const ExprT *E, bool IsRead = true); |
381 | |
382 | void recordUseOfWeak(const ObjCMessageExpr *Msg, |
383 | const ObjCPropertyDecl *Prop); |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | void markSafeWeakUse(const Expr *E); |
390 | |
391 | const WeakObjectUseMap &getWeakObjectUses() const { |
392 | return WeakObjectUses; |
393 | } |
394 | |
395 | void setHasBranchIntoScope() { |
396 | HasBranchIntoScope = true; |
397 | } |
398 | |
399 | void setHasBranchProtectedScope() { |
400 | HasBranchProtectedScope = true; |
401 | } |
402 | |
403 | void setHasIndirectGoto() { |
404 | HasIndirectGoto = true; |
405 | } |
406 | |
407 | void setHasDroppedStmt() { |
408 | HasDroppedStmt = true; |
409 | } |
410 | |
411 | void setHasOMPDeclareReductionCombiner() { |
412 | HasOMPDeclareReductionCombiner = true; |
413 | } |
414 | |
415 | void setHasFallthroughStmt() { |
416 | HasFallthroughStmt = true; |
417 | } |
418 | |
419 | void setHasCXXTry(SourceLocation TryLoc) { |
420 | setHasBranchProtectedScope(); |
421 | FirstCXXTryLoc = TryLoc; |
422 | } |
423 | |
424 | void setHasSEHTry(SourceLocation TryLoc) { |
425 | setHasBranchProtectedScope(); |
426 | FirstSEHTryLoc = TryLoc; |
427 | } |
428 | |
429 | bool NeedsScopeChecking() const { |
430 | return !HasDroppedStmt && |
431 | (HasIndirectGoto || |
432 | (HasBranchProtectedScope && HasBranchIntoScope)); |
433 | } |
434 | |
435 | |
436 | void addBlock(const BlockDecl *BD) { |
437 | Blocks.insert(BD); |
438 | } |
439 | |
440 | |
441 | void addByrefBlockVar(VarDecl *VD) { |
442 | ByrefBlockVars.push_back(VD); |
443 | } |
444 | |
445 | bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); } |
446 | |
447 | void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) { |
448 | (0) . __assert_fail ("FirstCoroutineStmtLoc.isInvalid() && \"first coroutine statement location already set\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 449, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(FirstCoroutineStmtLoc.isInvalid() && |
449 | (0) . __assert_fail ("FirstCoroutineStmtLoc.isInvalid() && \"first coroutine statement location already set\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 449, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "first coroutine statement location already set"); |
450 | FirstCoroutineStmtLoc = Loc; |
451 | FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword) |
452 | .Case("co_return", 0) |
453 | .Case("co_await", 1) |
454 | .Case("co_yield", 2); |
455 | } |
456 | |
457 | StringRef getFirstCoroutineStmtKeyword() const { |
458 | (0) . __assert_fail ("FirstCoroutineStmtLoc.isValid() && \"no coroutine statement available\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 459, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(FirstCoroutineStmtLoc.isValid() |
459 | (0) . __assert_fail ("FirstCoroutineStmtLoc.isValid() && \"no coroutine statement available\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 459, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> && "no coroutine statement available"); |
460 | switch (FirstCoroutineStmtKind) { |
461 | case 0: return "co_return"; |
462 | case 1: return "co_await"; |
463 | case 2: return "co_yield"; |
464 | default: |
465 | llvm_unreachable("FirstCoroutineStmtKind has an invalid value"); |
466 | }; |
467 | } |
468 | |
469 | void setNeedsCoroutineSuspends(bool value = true) { |
470 | (0) . __assert_fail ("(!value || CoroutineSuspends.first == nullptr) && \"we already have valid suspend points\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 471, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((!value || CoroutineSuspends.first == nullptr) && |
471 | (0) . __assert_fail ("(!value || CoroutineSuspends.first == nullptr) && \"we already have valid suspend points\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 471, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "we already have valid suspend points"); |
472 | NeedsCoroutineSuspends = value; |
473 | } |
474 | |
475 | bool hasInvalidCoroutineSuspends() const { |
476 | return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr; |
477 | } |
478 | |
479 | void setCoroutineSuspends(Stmt *Initial, Stmt *Final) { |
480 | (0) . __assert_fail ("Initial && Final && \"suspend points cannot be null\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 480, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Initial && Final && "suspend points cannot be null"); |
481 | (0) . __assert_fail ("CoroutineSuspends.first == nullptr && \"suspend points already set\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 481, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(CoroutineSuspends.first == nullptr && "suspend points already set"); |
482 | NeedsCoroutineSuspends = false; |
483 | CoroutineSuspends.first = Initial; |
484 | CoroutineSuspends.second = Final; |
485 | } |
486 | |
487 | |
488 | |
489 | void Clear(); |
490 | }; |
491 | |
492 | class Capture { |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | enum CaptureKind { |
507 | Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA |
508 | }; |
509 | enum { |
510 | IsNestedCapture = 0x1, |
511 | IsThisCaptured = 0x2 |
512 | }; |
513 | |
514 | |
515 | |
516 | llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis; |
517 | |
518 | |
519 | |
520 | |
521 | |
522 | llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind; |
523 | |
524 | |
525 | SourceLocation Loc; |
526 | |
527 | |
528 | SourceLocation EllipsisLoc; |
529 | |
530 | |
531 | |
532 | QualType CaptureType; |
533 | |
534 | |
535 | |
536 | bool ODRUsed = false; |
537 | |
538 | |
539 | |
540 | bool NonODRUsed = false; |
541 | |
542 | public: |
543 | Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, |
544 | SourceLocation Loc, SourceLocation EllipsisLoc, |
545 | QualType CaptureType, Expr *Cpy) |
546 | : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), |
547 | InitExprAndCaptureKind( |
548 | Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef |
549 | : Cap_ByCopy), |
550 | Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} |
551 | |
552 | enum IsThisCapture { ThisCapture }; |
553 | Capture(IsThisCapture, bool IsNested, SourceLocation Loc, |
554 | QualType CaptureType, Expr *Cpy, const bool ByCopy) |
555 | : VarAndNestedAndThis( |
556 | nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), |
557 | InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), |
558 | Loc(Loc), CaptureType(CaptureType) {} |
559 | |
560 | bool isThisCapture() const { |
561 | return VarAndNestedAndThis.getInt() & IsThisCaptured; |
562 | } |
563 | |
564 | bool isVariableCapture() const { |
565 | return !isThisCapture() && !isVLATypeCapture(); |
566 | } |
567 | |
568 | bool isCopyCapture() const { |
569 | return InitExprAndCaptureKind.getInt() == Cap_ByCopy; |
570 | } |
571 | |
572 | bool isReferenceCapture() const { |
573 | return InitExprAndCaptureKind.getInt() == Cap_ByRef; |
574 | } |
575 | |
576 | bool isBlockCapture() const { |
577 | return InitExprAndCaptureKind.getInt() == Cap_Block; |
578 | } |
579 | |
580 | bool isVLATypeCapture() const { |
581 | return InitExprAndCaptureKind.getInt() == Cap_VLA; |
582 | } |
583 | |
584 | bool isNested() const { |
585 | return VarAndNestedAndThis.getInt() & IsNestedCapture; |
586 | } |
587 | |
588 | bool isODRUsed() const { return ODRUsed; } |
589 | bool isNonODRUsed() const { return NonODRUsed; } |
590 | void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } |
591 | |
592 | VarDecl *getVariable() const { |
593 | assert(isVariableCapture()); |
594 | return VarAndNestedAndThis.getPointer(); |
595 | } |
596 | |
597 | |
598 | SourceLocation getLocation() const { return Loc; } |
599 | |
600 | |
601 | |
602 | SourceLocation getEllipsisLoc() const { return EllipsisLoc; } |
603 | |
604 | |
605 | |
606 | |
607 | QualType getCaptureType() const { |
608 | assert(!isThisCapture()); |
609 | return CaptureType; |
610 | } |
611 | |
612 | Expr *getInitExpr() const { |
613 | (0) . __assert_fail ("!isVLATypeCapture() && \"no init expression for type capture\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 613, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isVLATypeCapture() && "no init expression for type capture"); |
614 | return static_cast<Expr *>(InitExprAndCaptureKind.getPointer()); |
615 | } |
616 | }; |
617 | |
618 | class CapturingScopeInfo : public FunctionScopeInfo { |
619 | protected: |
620 | CapturingScopeInfo(const CapturingScopeInfo&) = default; |
621 | |
622 | public: |
623 | enum ImplicitCaptureStyle { |
624 | ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, |
625 | ImpCap_CapturedRegion |
626 | }; |
627 | |
628 | ImplicitCaptureStyle ImpCaptureStyle; |
629 | |
630 | CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) |
631 | : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {} |
632 | |
633 | |
634 | llvm::DenseMap<VarDecl*, unsigned> CaptureMap; |
635 | |
636 | |
637 | |
638 | unsigned CXXThisCaptureIndex = 0; |
639 | |
640 | |
641 | SmallVector<Capture, 4> Captures; |
642 | |
643 | |
644 | |
645 | bool HasImplicitReturnType = false; |
646 | |
647 | |
648 | |
649 | QualType ReturnType; |
650 | |
651 | void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested, |
652 | SourceLocation Loc, SourceLocation EllipsisLoc, |
653 | QualType CaptureType, Expr *Cpy) { |
654 | Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc, |
655 | EllipsisLoc, CaptureType, Cpy)); |
656 | CaptureMap[Var] = Captures.size(); |
657 | } |
658 | |
659 | void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) { |
660 | Captures.push_back(Capture( nullptr, false, |
661 | false, false, Loc, |
662 | SourceLocation(), CaptureType, |
663 | nullptr)); |
664 | } |
665 | |
666 | |
667 | |
668 | |
669 | void addThisCapture(bool isNested, SourceLocation Loc, |
670 | Expr *Cpy, bool ByCopy); |
671 | |
672 | |
673 | bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } |
674 | |
675 | |
676 | Capture &getCXXThisCapture() { |
677 | (0) . __assert_fail ("isCXXThisCaptured() && \"this has not been captured\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 677, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isCXXThisCaptured() && "this has not been captured"); |
678 | return Captures[CXXThisCaptureIndex - 1]; |
679 | } |
680 | |
681 | |
682 | bool isCaptured(VarDecl *Var) const { |
683 | return CaptureMap.count(Var); |
684 | } |
685 | |
686 | |
687 | bool isVLATypeCaptured(const VariableArrayType *VAT) const; |
688 | |
689 | |
690 | |
691 | Capture &getCapture(VarDecl *Var) { |
692 | (0) . __assert_fail ("isCaptured(Var) && \"Variable has not been captured\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 692, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isCaptured(Var) && "Variable has not been captured"); |
693 | return Captures[CaptureMap[Var] - 1]; |
694 | } |
695 | |
696 | const Capture &getCapture(VarDecl *Var) const { |
697 | llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known |
698 | = CaptureMap.find(Var); |
699 | (0) . __assert_fail ("Known != CaptureMap.end() && \"Variable has not been captured\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 699, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Known != CaptureMap.end() && "Variable has not been captured"); |
700 | return Captures[Known->second - 1]; |
701 | } |
702 | |
703 | static bool classof(const FunctionScopeInfo *FSI) { |
704 | return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda |
705 | || FSI->Kind == SK_CapturedRegion; |
706 | } |
707 | }; |
708 | |
709 | |
710 | class BlockScopeInfo final : public CapturingScopeInfo { |
711 | public: |
712 | BlockDecl *TheDecl; |
713 | |
714 | |
715 | |
716 | Scope *TheScope; |
717 | |
718 | |
719 | |
720 | QualType FunctionType; |
721 | |
722 | BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) |
723 | : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), |
724 | TheScope(BlockScope) { |
725 | Kind = SK_Block; |
726 | } |
727 | |
728 | ~BlockScopeInfo() override; |
729 | |
730 | static bool classof(const FunctionScopeInfo *FSI) { |
731 | return FSI->Kind == SK_Block; |
732 | } |
733 | }; |
734 | |
735 | |
736 | class CapturedRegionScopeInfo final : public CapturingScopeInfo { |
737 | public: |
738 | |
739 | CapturedDecl *TheCapturedDecl; |
740 | |
741 | |
742 | RecordDecl *TheRecordDecl; |
743 | |
744 | |
745 | Scope *TheScope; |
746 | |
747 | |
748 | ImplicitParamDecl *ContextParam; |
749 | |
750 | |
751 | unsigned short CapRegionKind; |
752 | |
753 | unsigned short OpenMPLevel; |
754 | |
755 | CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD, |
756 | RecordDecl *RD, ImplicitParamDecl *Context, |
757 | CapturedRegionKind K, unsigned OpenMPLevel) |
758 | : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), |
759 | TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), |
760 | ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) { |
761 | Kind = SK_CapturedRegion; |
762 | } |
763 | |
764 | ~CapturedRegionScopeInfo() override; |
765 | |
766 | |
767 | StringRef getRegionName() const { |
768 | switch (CapRegionKind) { |
769 | case CR_Default: |
770 | return "default captured statement"; |
771 | case CR_ObjCAtFinally: |
772 | return "Objective-C @finally statement"; |
773 | case CR_OpenMP: |
774 | return "OpenMP region"; |
775 | } |
776 | llvm_unreachable("Invalid captured region kind!"); |
777 | } |
778 | |
779 | static bool classof(const FunctionScopeInfo *FSI) { |
780 | return FSI->Kind == SK_CapturedRegion; |
781 | } |
782 | }; |
783 | |
784 | class LambdaScopeInfo final : public CapturingScopeInfo { |
785 | public: |
786 | |
787 | CXXRecordDecl *Lambda = nullptr; |
788 | |
789 | |
790 | CXXMethodDecl *CallOperator = nullptr; |
791 | |
792 | |
793 | SourceRange IntroducerRange; |
794 | |
795 | |
796 | |
797 | SourceLocation CaptureDefaultLoc; |
798 | |
799 | |
800 | |
801 | unsigned NumExplicitCaptures = 0; |
802 | |
803 | |
804 | bool Mutable = false; |
805 | |
806 | |
807 | bool ExplicitParams = false; |
808 | |
809 | |
810 | CleanupInfo Cleanup; |
811 | |
812 | |
813 | bool ContainsUnexpandedParameterPack = false; |
814 | |
815 | |
816 | |
817 | unsigned AutoTemplateParameterDepth = 0; |
818 | |
819 | |
820 | |
821 | |
822 | |
823 | |
824 | SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams; |
825 | |
826 | |
827 | |
828 | |
829 | TemplateParameterList *GLTemplateParameterList = nullptr; |
830 | |
831 | |
832 | |
833 | |
834 | |
835 | |
836 | |
837 | |
838 | |
839 | |
840 | |
841 | |
842 | |
843 | |
844 | llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs; |
845 | |
846 | |
847 | |
848 | |
849 | |
850 | llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs; |
851 | |
852 | |
853 | llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges; |
854 | |
855 | |
856 | |
857 | |
858 | struct ShadowedOuterDecl { |
859 | const VarDecl *VD; |
860 | const VarDecl *ShadowedDecl; |
861 | }; |
862 | llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls; |
863 | |
864 | SourceLocation PotentialThisCaptureLocation; |
865 | |
866 | LambdaScopeInfo(DiagnosticsEngine &Diag) |
867 | : CapturingScopeInfo(Diag, ImpCap_None) { |
868 | Kind = SK_Lambda; |
869 | } |
870 | |
871 | |
872 | void finishedExplicitCaptures() { |
873 | NumExplicitCaptures = Captures.size(); |
874 | } |
875 | |
876 | static bool classof(const FunctionScopeInfo *FSI) { |
877 | return FSI->Kind == SK_Lambda; |
878 | } |
879 | |
880 | |
881 | |
882 | bool isGenericLambda() const { |
883 | return !AutoTemplateParams.empty() || GLTemplateParameterList; |
884 | } |
885 | |
886 | |
887 | |
888 | |
889 | |
890 | |
891 | |
892 | |
893 | |
894 | |
895 | |
896 | |
897 | |
898 | |
899 | |
900 | |
901 | |
902 | |
903 | void addPotentialCapture(Expr *VarExpr) { |
904 | (VarExpr) || isa(VarExpr)", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 904, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr)); |
905 | PotentiallyCapturingExprs.push_back(VarExpr); |
906 | } |
907 | |
908 | void addPotentialThisCapture(SourceLocation Loc) { |
909 | PotentialThisCaptureLocation = Loc; |
910 | } |
911 | |
912 | bool hasPotentialThisCapture() const { |
913 | return PotentialThisCaptureLocation.isValid(); |
914 | } |
915 | |
916 | |
917 | |
918 | |
919 | |
920 | |
921 | |
922 | |
923 | |
924 | |
925 | |
926 | |
927 | |
928 | |
929 | |
930 | |
931 | |
932 | |
933 | |
934 | |
935 | |
936 | |
937 | |
938 | |
939 | |
940 | |
941 | |
942 | |
943 | |
944 | |
945 | |
946 | |
947 | |
948 | |
949 | |
950 | |
951 | |
952 | |
953 | |
954 | |
955 | void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { |
956 | (CapturingVarExpr) || isa(CapturingVarExpr)", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 957, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isa<DeclRefExpr>(CapturingVarExpr) |
957 | (CapturingVarExpr) || isa(CapturingVarExpr)", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 957, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> || isa<MemberExpr>(CapturingVarExpr)); |
958 | NonODRUsedCapturingExprs.insert(CapturingVarExpr); |
959 | } |
960 | bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const { |
961 | (CapturingVarExpr) || isa(CapturingVarExpr)", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 962, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isa<DeclRefExpr>(CapturingVarExpr) |
962 | (CapturingVarExpr) || isa(CapturingVarExpr)", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/ScopeInfo.h", 962, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> || isa<MemberExpr>(CapturingVarExpr)); |
963 | return NonODRUsedCapturingExprs.count(CapturingVarExpr); |
964 | } |
965 | void removePotentialCapture(Expr *E) { |
966 | PotentiallyCapturingExprs.erase( |
967 | std::remove(PotentiallyCapturingExprs.begin(), |
968 | PotentiallyCapturingExprs.end(), E), |
969 | PotentiallyCapturingExprs.end()); |
970 | } |
971 | void clearPotentialCaptures() { |
972 | PotentiallyCapturingExprs.clear(); |
973 | PotentialThisCaptureLocation = SourceLocation(); |
974 | } |
975 | unsigned getNumPotentialVariableCaptures() const { |
976 | return PotentiallyCapturingExprs.size(); |
977 | } |
978 | |
979 | bool hasPotentialCaptures() const { |
980 | return getNumPotentialVariableCaptures() || |
981 | PotentialThisCaptureLocation.isValid(); |
982 | } |
983 | |
984 | |
985 | |
986 | void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const; |
987 | }; |
988 | |
989 | FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() |
990 | : Base(nullptr, false) {} |
991 | |
992 | FunctionScopeInfo::WeakObjectProfileTy |
993 | FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { |
994 | FunctionScopeInfo::WeakObjectProfileTy Result; |
995 | Result.Base.setInt(true); |
996 | return Result; |
997 | } |
998 | |
999 | template <typename ExprT> |
1000 | void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { |
1001 | assert(E); |
1002 | WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)]; |
1003 | Uses.push_back(WeakUseTy(E, IsRead)); |
1004 | } |
1005 | |
1006 | inline void |
1007 | CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, |
1008 | Expr *Cpy, |
1009 | const bool ByCopy) { |
1010 | Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, QualType(), |
1011 | Cpy, ByCopy)); |
1012 | CXXThisCaptureIndex = Captures.size(); |
1013 | } |
1014 | |
1015 | } |
1016 | |
1017 | } |
1018 | |
1019 | #endif |
1020 | |