• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===//
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 defines FunctionScopeInfo and its subclasses, which contain
11 // information about a single function, block, lambda, or method body.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
16 #define LLVM_CLANG_SEMA_SCOPE_INFO_H
17 
18 #include "clang/AST/Type.h"
19 #include "clang/Basic/PartialDiagnostic.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallVector.h"
22 
23 namespace clang {
24 
25 class Decl;
26 class BlockDecl;
27 class CXXMethodDecl;
28 class ObjCPropertyDecl;
29 class IdentifierInfo;
30 class LabelDecl;
31 class ReturnStmt;
32 class Scope;
33 class SwitchStmt;
34 class VarDecl;
35 class DeclRefExpr;
36 class ObjCIvarRefExpr;
37 class ObjCPropertyRefExpr;
38 class ObjCMessageExpr;
39 
40 namespace sema {
41 
42 /// \brief Contains information about the compound statement currently being
43 /// parsed.
44 class CompoundScopeInfo {
45 public:
CompoundScopeInfo()46   CompoundScopeInfo()
47     : HasEmptyLoopBodies(false) { }
48 
49   /// \brief Whether this compound stamement contains `for' or `while' loops
50   /// with empty bodies.
51   bool HasEmptyLoopBodies;
52 
setHasEmptyLoopBodies()53   void setHasEmptyLoopBodies() {
54     HasEmptyLoopBodies = true;
55   }
56 };
57 
58 class PossiblyUnreachableDiag {
59 public:
60   PartialDiagnostic PD;
61   SourceLocation Loc;
62   const Stmt *stmt;
63 
PossiblyUnreachableDiag(const PartialDiagnostic & PD,SourceLocation Loc,const Stmt * stmt)64   PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
65                           const Stmt *stmt)
66     : PD(PD), Loc(Loc), stmt(stmt) {}
67 };
68 
69 /// \brief Retains information about a function, method, or block that is
70 /// currently being parsed.
71 class FunctionScopeInfo {
72 protected:
73   enum ScopeKind {
74     SK_Function,
75     SK_Block,
76     SK_Lambda
77   };
78 
79 public:
80   /// \brief What kind of scope we are describing.
81   ///
82   ScopeKind Kind;
83 
84   /// \brief Whether this function contains a VLA, \@try, try, C++
85   /// initializer, or anything else that can't be jumped past.
86   bool HasBranchProtectedScope;
87 
88   /// \brief Whether this function contains any switches or direct gotos.
89   bool HasBranchIntoScope;
90 
91   /// \brief Whether this function contains any indirect gotos.
92   bool HasIndirectGoto;
93 
94   /// \brief Whether a statement was dropped because it was invalid.
95   bool HasDroppedStmt;
96 
97   /// A flag that is set when parsing a method that must call super's
98   /// implementation, such as \c -dealloc, \c -finalize, or any method marked
99   /// with \c __attribute__((objc_requires_super)).
100   bool ObjCShouldCallSuper;
101 
102   /// \brief Used to determine if errors occurred in this function or block.
103   DiagnosticErrorTrap ErrorTrap;
104 
105   /// SwitchStack - This is the current set of active switch statements in the
106   /// block.
107   SmallVector<SwitchStmt*, 8> SwitchStack;
108 
109   /// \brief The list of return statements that occur within the function or
110   /// block, if there is any chance of applying the named return value
111   /// optimization, or if we need to infer a return type.
112   SmallVector<ReturnStmt*, 4> Returns;
113 
114   /// \brief The stack of currently active compound stamement scopes in the
115   /// function.
116   SmallVector<CompoundScopeInfo, 4> CompoundScopes;
117 
118   /// \brief A list of PartialDiagnostics created but delayed within the
119   /// current function scope.  These diagnostics are vetted for reachability
120   /// prior to being emitted.
121   SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
122 
123 public:
124   /// Represents a simple identification of a weak object.
125   ///
126   /// Part of the implementation of -Wrepeated-use-of-weak.
127   ///
128   /// This is used to determine if two weak accesses refer to the same object.
129   /// Here are some examples of how various accesses are "profiled":
130   ///
131   /// Access Expression |     "Base" Decl     |          "Property" Decl
132   /// :---------------: | :-----------------: | :------------------------------:
133   /// self.property     | self (VarDecl)      | property (ObjCPropertyDecl)
134   /// self.implicitProp | self (VarDecl)      | -implicitProp (ObjCMethodDecl)
135   /// self->ivar.prop   | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl)
136   /// cxxObj.obj.prop   | obj (FieldDecl)     | prop (ObjCPropertyDecl)
137   /// [self foo].prop   | 0 (unknown)         | prop (ObjCPropertyDecl)
138   /// self.prop1.prop2  | prop1 (ObjCPropertyDecl)    | prop2 (ObjCPropertyDecl)
139   /// MyClass.prop      | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
140   /// weakVar           | 0 (known)           | weakVar (VarDecl)
141   /// self->weakIvar    | self (VarDecl)      | weakIvar (ObjCIvarDecl)
142   ///
143   /// Objects are identified with only two Decls to make it reasonably fast to
144   /// compare them.
145   class WeakObjectProfileTy {
146     /// The base object decl, as described in the class documentation.
147     ///
148     /// The extra flag is "true" if the Base and Property are enough to uniquely
149     /// identify the object in memory.
150     ///
151     /// \sa isExactProfile()
152     typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy;
153     BaseInfoTy Base;
154 
155     /// The "property" decl, as described in the class documentation.
156     ///
157     /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the
158     /// case of "implicit" properties (regular methods accessed via dot syntax).
159     const NamedDecl *Property;
160 
161     /// Used to find the proper base profile for a given base expression.
162     static BaseInfoTy getBaseInfo(const Expr *BaseE);
163 
164     // For use in DenseMap.
165     friend class DenseMapInfo;
166     inline WeakObjectProfileTy();
167     static inline WeakObjectProfileTy getSentinel();
168 
169   public:
170     WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
171     WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
172     WeakObjectProfileTy(const DeclRefExpr *RE);
173     WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
174 
getBase()175     const NamedDecl *getBase() const { return Base.getPointer(); }
getProperty()176     const NamedDecl *getProperty() const { return Property; }
177 
178     /// Returns true if the object base specifies a known object in memory,
179     /// rather than, say, an instance variable or property of another object.
180     ///
181     /// Note that this ignores the effects of aliasing; that is, \c foo.bar is
182     /// considered an exact profile if \c foo is a local variable, even if
183     /// another variable \c foo2 refers to the same object as \c foo.
184     ///
185     /// For increased precision, accesses with base variables that are
186     /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to
187     /// be exact, though this is not true for arbitrary variables
188     /// (foo.prop1.prop2).
isExactProfile()189     bool isExactProfile() const {
190       return Base.getInt();
191     }
192 
193     bool operator==(const WeakObjectProfileTy &Other) const {
194       return Base == Other.Base && Property == Other.Property;
195     }
196 
197     // For use in DenseMap.
198     // We can't specialize the usual llvm::DenseMapInfo at the end of the file
199     // because by that point the DenseMap in FunctionScopeInfo has already been
200     // instantiated.
201     class DenseMapInfo {
202     public:
getEmptyKey()203       static inline WeakObjectProfileTy getEmptyKey() {
204         return WeakObjectProfileTy();
205       }
getTombstoneKey()206       static inline WeakObjectProfileTy getTombstoneKey() {
207         return WeakObjectProfileTy::getSentinel();
208       }
209 
getHashValue(const WeakObjectProfileTy & Val)210       static unsigned getHashValue(const WeakObjectProfileTy &Val) {
211         typedef std::pair<BaseInfoTy, const NamedDecl *> Pair;
212         return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
213                                                            Val.Property));
214       }
215 
isEqual(const WeakObjectProfileTy & LHS,const WeakObjectProfileTy & RHS)216       static bool isEqual(const WeakObjectProfileTy &LHS,
217                           const WeakObjectProfileTy &RHS) {
218         return LHS == RHS;
219       }
220     };
221   };
222 
223   /// Represents a single use of a weak object.
224   ///
225   /// Stores both the expression and whether the access is potentially unsafe
226   /// (i.e. it could potentially be warned about).
227   ///
228   /// Part of the implementation of -Wrepeated-use-of-weak.
229   class WeakUseTy {
230     llvm::PointerIntPair<const Expr *, 1, bool> Rep;
231   public:
WeakUseTy(const Expr * Use,bool IsRead)232     WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
233 
getUseExpr()234     const Expr *getUseExpr() const { return Rep.getPointer(); }
isUnsafe()235     bool isUnsafe() const { return Rep.getInt(); }
markSafe()236     void markSafe() { Rep.setInt(false); }
237 
238     bool operator==(const WeakUseTy &Other) const {
239       return Rep == Other.Rep;
240     }
241   };
242 
243   /// Used to collect uses of a particular weak object in a function body.
244   ///
245   /// Part of the implementation of -Wrepeated-use-of-weak.
246   typedef SmallVector<WeakUseTy, 4> WeakUseVector;
247 
248   /// Used to collect all uses of weak objects in a function body.
249   ///
250   /// Part of the implementation of -Wrepeated-use-of-weak.
251   typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
252                               WeakObjectProfileTy::DenseMapInfo>
253           WeakObjectUseMap;
254 
255 private:
256   /// Used to collect all uses of weak objects in this function body.
257   ///
258   /// Part of the implementation of -Wrepeated-use-of-weak.
259   WeakObjectUseMap WeakObjectUses;
260 
261 public:
262   /// Record that a weak object was accessed.
263   ///
264   /// Part of the implementation of -Wrepeated-use-of-weak.
265   template <typename ExprT>
266   inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
267 
268   void recordUseOfWeak(const ObjCMessageExpr *Msg,
269                        const ObjCPropertyDecl *Prop);
270 
271   /// Record that a given expression is a "safe" access of a weak object (e.g.
272   /// assigning it to a strong variable.)
273   ///
274   /// Part of the implementation of -Wrepeated-use-of-weak.
275   void markSafeWeakUse(const Expr *E);
276 
getWeakObjectUses()277   const WeakObjectUseMap &getWeakObjectUses() const {
278     return WeakObjectUses;
279   }
280 
setHasBranchIntoScope()281   void setHasBranchIntoScope() {
282     HasBranchIntoScope = true;
283   }
284 
setHasBranchProtectedScope()285   void setHasBranchProtectedScope() {
286     HasBranchProtectedScope = true;
287   }
288 
setHasIndirectGoto()289   void setHasIndirectGoto() {
290     HasIndirectGoto = true;
291   }
292 
setHasDroppedStmt()293   void setHasDroppedStmt() {
294     HasDroppedStmt = true;
295   }
296 
NeedsScopeChecking()297   bool NeedsScopeChecking() const {
298     return !HasDroppedStmt &&
299         (HasIndirectGoto ||
300           (HasBranchProtectedScope && HasBranchIntoScope));
301   }
302 
FunctionScopeInfo(DiagnosticsEngine & Diag)303   FunctionScopeInfo(DiagnosticsEngine &Diag)
304     : Kind(SK_Function),
305       HasBranchProtectedScope(false),
306       HasBranchIntoScope(false),
307       HasIndirectGoto(false),
308       HasDroppedStmt(false),
309       ObjCShouldCallSuper(false),
310       ErrorTrap(Diag) { }
311 
312   virtual ~FunctionScopeInfo();
313 
314   /// \brief Clear out the information in this function scope, making it
315   /// suitable for reuse.
316   void Clear();
317 };
318 
319 class CapturingScopeInfo : public FunctionScopeInfo {
320 public:
321   enum ImplicitCaptureStyle {
322     ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block
323   };
324 
325   ImplicitCaptureStyle ImpCaptureStyle;
326 
327   class Capture {
328     // There are two categories of capture: capturing 'this', and capturing
329     // local variables.  There are three ways to capture a local variable:
330     // capture by copy in the C++11 sense, capture by reference
331     // in the C++11 sense, and __block capture.  Lambdas explicitly specify
332     // capture by copy or capture by reference.  For blocks, __block capture
333     // applies to variables with that annotation, variables of reference type
334     // are captured by reference, and other variables are captured by copy.
335     enum CaptureKind {
336       Cap_This, Cap_ByCopy, Cap_ByRef, Cap_Block
337     };
338 
339     // The variable being captured (if we are not capturing 'this'),
340     // and misc bits descibing the capture.
341     llvm::PointerIntPair<VarDecl*, 2, CaptureKind> VarAndKind;
342 
343     // Expression to initialize a field of the given type, and whether this
344     // is a nested capture; the expression is only required if we are
345     // capturing ByVal and the variable's type has a non-trivial
346     // copy constructor.
347     llvm::PointerIntPair<Expr*, 1, bool> CopyExprAndNested;
348 
349     /// \brief The source location at which the first capture occurred..
350     SourceLocation Loc;
351 
352     /// \brief The location of the ellipsis that expands a parameter pack.
353     SourceLocation EllipsisLoc;
354 
355     /// \brief The type as it was captured, which is in effect the type of the
356     /// non-static data member that would hold the capture.
357     QualType CaptureType;
358 
359   public:
Capture(VarDecl * Var,bool block,bool byRef,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)360     Capture(VarDecl *Var, bool block, bool byRef, bool isNested,
361             SourceLocation Loc, SourceLocation EllipsisLoc,
362             QualType CaptureType, Expr *Cpy)
363       : VarAndKind(Var, block ? Cap_Block : byRef ? Cap_ByRef : Cap_ByCopy),
364         CopyExprAndNested(Cpy, isNested), Loc(Loc), EllipsisLoc(EllipsisLoc),
365         CaptureType(CaptureType){}
366 
367     enum IsThisCapture { ThisCapture };
Capture(IsThisCapture,bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)368     Capture(IsThisCapture, bool isNested, SourceLocation Loc,
369             QualType CaptureType, Expr *Cpy)
370       : VarAndKind(0, Cap_This), CopyExprAndNested(Cpy, isNested), Loc(Loc),
371         EllipsisLoc(), CaptureType(CaptureType) { }
372 
isThisCapture()373     bool isThisCapture() const { return VarAndKind.getInt() == Cap_This; }
isVariableCapture()374     bool isVariableCapture() const { return !isThisCapture(); }
isCopyCapture()375     bool isCopyCapture() const { return VarAndKind.getInt() == Cap_ByCopy; }
isReferenceCapture()376     bool isReferenceCapture() const { return VarAndKind.getInt() == Cap_ByRef; }
isBlockCapture()377     bool isBlockCapture() const { return VarAndKind.getInt() == Cap_Block; }
isNested()378     bool isNested() { return CopyExprAndNested.getInt(); }
379 
getVariable()380     VarDecl *getVariable() const {
381       return VarAndKind.getPointer();
382     }
383 
384     /// \brief Retrieve the location at which this variable was captured.
getLocation()385     SourceLocation getLocation() const { return Loc; }
386 
387     /// \brief Retrieve the source location of the ellipsis, whose presence
388     /// indicates that the capture is a pack expansion.
getEllipsisLoc()389     SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
390 
391     /// \brief Retrieve the capture type for this capture, which is effectively
392     /// the type of the non-static data member in the lambda/block structure
393     /// that would store this capture.
getCaptureType()394     QualType getCaptureType() const { return CaptureType; }
395 
getCopyExpr()396     Expr *getCopyExpr() const {
397       return CopyExprAndNested.getPointer();
398     }
399   };
400 
CapturingScopeInfo(DiagnosticsEngine & Diag,ImplicitCaptureStyle Style)401   CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
402     : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0),
403       HasImplicitReturnType(false)
404      {}
405 
406   /// CaptureMap - A map of captured variables to (index+1) into Captures.
407   llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
408 
409   /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
410   /// zero if 'this' is not captured.
411   unsigned CXXThisCaptureIndex;
412 
413   /// Captures - The captures.
414   SmallVector<Capture, 4> Captures;
415 
416   /// \brief - Whether the target type of return statements in this context
417   /// is deduced (e.g. a lambda or block with omitted return type).
418   bool HasImplicitReturnType;
419 
420   /// ReturnType - The target type of return statements in this context,
421   /// or null if unknown.
422   QualType ReturnType;
423 
addCapture(VarDecl * Var,bool isBlock,bool isByref,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,Expr * Cpy)424   void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
425                   SourceLocation Loc, SourceLocation EllipsisLoc,
426                   QualType CaptureType, Expr *Cpy) {
427     Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
428                                EllipsisLoc, CaptureType, Cpy));
429     CaptureMap[Var] = Captures.size();
430   }
431 
432   void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
433                       Expr *Cpy);
434 
435   /// \brief Determine whether the C++ 'this' is captured.
isCXXThisCaptured()436   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
437 
438   /// \brief Retrieve the capture of C++ 'this', if it has been captured.
getCXXThisCapture()439   Capture &getCXXThisCapture() {
440     assert(isCXXThisCaptured() && "this has not been captured");
441     return Captures[CXXThisCaptureIndex - 1];
442   }
443 
444   /// \brief Determine whether the given variable has been captured.
isCaptured(VarDecl * Var)445   bool isCaptured(VarDecl *Var) const {
446     return CaptureMap.count(Var);
447   }
448 
449   /// \brief Retrieve the capture of the given variable, if it has been
450   /// captured already.
getCapture(VarDecl * Var)451   Capture &getCapture(VarDecl *Var) {
452     assert(isCaptured(Var) && "Variable has not been captured");
453     return Captures[CaptureMap[Var] - 1];
454   }
455 
getCapture(VarDecl * Var)456   const Capture &getCapture(VarDecl *Var) const {
457     llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known
458       = CaptureMap.find(Var);
459     assert(Known != CaptureMap.end() && "Variable has not been captured");
460     return Captures[Known->second - 1];
461   }
462 
classof(const FunctionScopeInfo * FSI)463   static bool classof(const FunctionScopeInfo *FSI) {
464     return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda;
465   }
466 };
467 
468 /// \brief Retains information about a block that is currently being parsed.
469 class BlockScopeInfo : public CapturingScopeInfo {
470 public:
471   BlockDecl *TheDecl;
472 
473   /// TheScope - This is the scope for the block itself, which contains
474   /// arguments etc.
475   Scope *TheScope;
476 
477   /// BlockType - The function type of the block, if one was given.
478   /// Its return type may be BuiltinType::Dependent.
479   QualType FunctionType;
480 
BlockScopeInfo(DiagnosticsEngine & Diag,Scope * BlockScope,BlockDecl * Block)481   BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
482     : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
483       TheScope(BlockScope)
484   {
485     Kind = SK_Block;
486   }
487 
488   virtual ~BlockScopeInfo();
489 
classof(const FunctionScopeInfo * FSI)490   static bool classof(const FunctionScopeInfo *FSI) {
491     return FSI->Kind == SK_Block;
492   }
493 };
494 
495 class LambdaScopeInfo : public CapturingScopeInfo {
496 public:
497   /// \brief The class that describes the lambda.
498   CXXRecordDecl *Lambda;
499 
500   /// \brief The class that describes the lambda.
501   CXXMethodDecl *CallOperator;
502 
503   /// \brief Source range covering the lambda introducer [...].
504   SourceRange IntroducerRange;
505 
506   /// \brief The number of captures in the \c Captures list that are
507   /// explicit captures.
508   unsigned NumExplicitCaptures;
509 
510   /// \brief Whether this is a mutable lambda.
511   bool Mutable;
512 
513   /// \brief Whether the (empty) parameter list is explicit.
514   bool ExplicitParams;
515 
516   /// \brief Whether any of the capture expressions requires cleanups.
517   bool ExprNeedsCleanups;
518 
519   /// \brief Whether the lambda contains an unexpanded parameter pack.
520   bool ContainsUnexpandedParameterPack;
521 
522   /// \brief Variables used to index into by-copy array captures.
523   SmallVector<VarDecl *, 4> ArrayIndexVars;
524 
525   /// \brief Offsets into the ArrayIndexVars array at which each capture starts
526   /// its list of array index variables.
527   SmallVector<unsigned, 4> ArrayIndexStarts;
528 
LambdaScopeInfo(DiagnosticsEngine & Diag,CXXRecordDecl * Lambda,CXXMethodDecl * CallOperator)529   LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
530                   CXXMethodDecl *CallOperator)
531     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
532       CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
533       ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
534   {
535     Kind = SK_Lambda;
536   }
537 
538   virtual ~LambdaScopeInfo();
539 
540   /// \brief Note when
finishedExplicitCaptures()541   void finishedExplicitCaptures() {
542     NumExplicitCaptures = Captures.size();
543   }
544 
classof(const FunctionScopeInfo * FSI)545   static bool classof(const FunctionScopeInfo *FSI) {
546     return FSI->Kind == SK_Lambda;
547   }
548 };
549 
550 
WeakObjectProfileTy()551 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
552   : Base(0, false), Property(0) {}
553 
554 FunctionScopeInfo::WeakObjectProfileTy
getSentinel()555 FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
556   FunctionScopeInfo::WeakObjectProfileTy Result;
557   Result.Base.setInt(true);
558   return Result;
559 }
560 
561 template <typename ExprT>
recordUseOfWeak(const ExprT * E,bool IsRead)562 void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
563   assert(E);
564   WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
565   Uses.push_back(WeakUseTy(E, IsRead));
566 }
567 
568 inline void
addThisCapture(bool isNested,SourceLocation Loc,QualType CaptureType,Expr * Cpy)569 CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
570                                    QualType CaptureType, Expr *Cpy) {
571   Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
572                              Cpy));
573   CXXThisCaptureIndex = Captures.size();
574 
575   if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(this))
576     LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
577 }
578 
579 } // end namespace sema
580 } // end namespace clang
581 
582 #endif
583