106f32e7eSjoerg //===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file defines FunctionScopeInfo and its subclasses, which contain
1006f32e7eSjoerg // information about a single function, block, lambda, or method body.
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg 
1406f32e7eSjoerg #ifndef LLVM_CLANG_SEMA_SCOPEINFO_H
1506f32e7eSjoerg #define LLVM_CLANG_SEMA_SCOPEINFO_H
1606f32e7eSjoerg 
1706f32e7eSjoerg #include "clang/AST/Expr.h"
1806f32e7eSjoerg #include "clang/AST/ExprCXX.h"
1906f32e7eSjoerg #include "clang/AST/Type.h"
2006f32e7eSjoerg #include "clang/Basic/CapturedStmt.h"
2106f32e7eSjoerg #include "clang/Basic/LLVM.h"
2206f32e7eSjoerg #include "clang/Basic/PartialDiagnostic.h"
2306f32e7eSjoerg #include "clang/Basic/SourceLocation.h"
2406f32e7eSjoerg #include "clang/Sema/CleanupInfo.h"
25*13fbcb42Sjoerg #include "clang/Sema/DeclSpec.h"
2606f32e7eSjoerg #include "llvm/ADT/DenseMap.h"
2706f32e7eSjoerg #include "llvm/ADT/DenseMapInfo.h"
2806f32e7eSjoerg #include "llvm/ADT/MapVector.h"
2906f32e7eSjoerg #include "llvm/ADT/PointerIntPair.h"
3006f32e7eSjoerg #include "llvm/ADT/SmallPtrSet.h"
3106f32e7eSjoerg #include "llvm/ADT/SmallSet.h"
3206f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
3306f32e7eSjoerg #include "llvm/ADT/StringRef.h"
3406f32e7eSjoerg #include "llvm/ADT/StringSwitch.h"
3506f32e7eSjoerg #include "llvm/ADT/TinyPtrVector.h"
3606f32e7eSjoerg #include "llvm/Support/Casting.h"
3706f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
3806f32e7eSjoerg #include <algorithm>
3906f32e7eSjoerg #include <cassert>
4006f32e7eSjoerg #include <utility>
4106f32e7eSjoerg 
4206f32e7eSjoerg namespace clang {
4306f32e7eSjoerg 
4406f32e7eSjoerg class BlockDecl;
4506f32e7eSjoerg class CapturedDecl;
4606f32e7eSjoerg class CXXMethodDecl;
4706f32e7eSjoerg class CXXRecordDecl;
4806f32e7eSjoerg class ImplicitParamDecl;
4906f32e7eSjoerg class NamedDecl;
5006f32e7eSjoerg class ObjCIvarRefExpr;
5106f32e7eSjoerg class ObjCMessageExpr;
5206f32e7eSjoerg class ObjCPropertyDecl;
5306f32e7eSjoerg class ObjCPropertyRefExpr;
5406f32e7eSjoerg class ParmVarDecl;
5506f32e7eSjoerg class RecordDecl;
5606f32e7eSjoerg class ReturnStmt;
5706f32e7eSjoerg class Scope;
5806f32e7eSjoerg class Stmt;
5906f32e7eSjoerg class SwitchStmt;
6006f32e7eSjoerg class TemplateParameterList;
6106f32e7eSjoerg class TemplateTypeParmDecl;
6206f32e7eSjoerg class VarDecl;
6306f32e7eSjoerg 
6406f32e7eSjoerg namespace sema {
6506f32e7eSjoerg 
6606f32e7eSjoerg /// Contains information about the compound statement currently being
6706f32e7eSjoerg /// parsed.
6806f32e7eSjoerg class CompoundScopeInfo {
6906f32e7eSjoerg public:
7006f32e7eSjoerg   /// Whether this compound stamement contains `for' or `while' loops
7106f32e7eSjoerg   /// with empty bodies.
7206f32e7eSjoerg   bool HasEmptyLoopBodies = false;
7306f32e7eSjoerg 
7406f32e7eSjoerg   /// Whether this compound statement corresponds to a GNU statement
7506f32e7eSjoerg   /// expression.
7606f32e7eSjoerg   bool IsStmtExpr;
7706f32e7eSjoerg 
CompoundScopeInfo(bool IsStmtExpr)7806f32e7eSjoerg   CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {}
7906f32e7eSjoerg 
setHasEmptyLoopBodies()8006f32e7eSjoerg   void setHasEmptyLoopBodies() {
8106f32e7eSjoerg     HasEmptyLoopBodies = true;
8206f32e7eSjoerg   }
8306f32e7eSjoerg };
8406f32e7eSjoerg 
8506f32e7eSjoerg class PossiblyUnreachableDiag {
8606f32e7eSjoerg public:
8706f32e7eSjoerg   PartialDiagnostic PD;
8806f32e7eSjoerg   SourceLocation Loc;
8906f32e7eSjoerg   llvm::TinyPtrVector<const Stmt*> Stmts;
9006f32e7eSjoerg 
PossiblyUnreachableDiag(const PartialDiagnostic & PD,SourceLocation Loc,ArrayRef<const Stmt * > Stmts)9106f32e7eSjoerg   PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
9206f32e7eSjoerg                           ArrayRef<const Stmt *> Stmts)
9306f32e7eSjoerg       : PD(PD), Loc(Loc), Stmts(Stmts) {}
9406f32e7eSjoerg };
9506f32e7eSjoerg 
9606f32e7eSjoerg /// Retains information about a function, method, or block that is
9706f32e7eSjoerg /// currently being parsed.
9806f32e7eSjoerg class FunctionScopeInfo {
9906f32e7eSjoerg protected:
10006f32e7eSjoerg   enum ScopeKind {
10106f32e7eSjoerg     SK_Function,
10206f32e7eSjoerg     SK_Block,
10306f32e7eSjoerg     SK_Lambda,
10406f32e7eSjoerg     SK_CapturedRegion
10506f32e7eSjoerg   };
10606f32e7eSjoerg 
10706f32e7eSjoerg public:
10806f32e7eSjoerg   /// What kind of scope we are describing.
10906f32e7eSjoerg   ScopeKind Kind : 3;
11006f32e7eSjoerg 
11106f32e7eSjoerg   /// Whether this function contains a VLA, \@try, try, C++
11206f32e7eSjoerg   /// initializer, or anything else that can't be jumped past.
11306f32e7eSjoerg   bool HasBranchProtectedScope : 1;
11406f32e7eSjoerg 
11506f32e7eSjoerg   /// Whether this function contains any switches or direct gotos.
11606f32e7eSjoerg   bool HasBranchIntoScope : 1;
11706f32e7eSjoerg 
11806f32e7eSjoerg   /// Whether this function contains any indirect gotos.
11906f32e7eSjoerg   bool HasIndirectGoto : 1;
12006f32e7eSjoerg 
121*13fbcb42Sjoerg   /// Whether this function contains any statement marked with
122*13fbcb42Sjoerg   /// \c [[clang::musttail]].
123*13fbcb42Sjoerg   bool HasMustTail : 1;
124*13fbcb42Sjoerg 
12506f32e7eSjoerg   /// Whether a statement was dropped because it was invalid.
12606f32e7eSjoerg   bool HasDroppedStmt : 1;
12706f32e7eSjoerg 
12806f32e7eSjoerg   /// True if current scope is for OpenMP declare reduction combiner.
12906f32e7eSjoerg   bool HasOMPDeclareReductionCombiner : 1;
13006f32e7eSjoerg 
13106f32e7eSjoerg   /// Whether there is a fallthrough statement in this function.
13206f32e7eSjoerg   bool HasFallthroughStmt : 1;
13306f32e7eSjoerg 
134*13fbcb42Sjoerg   /// Whether this function uses constrained floating point intrinsics
135*13fbcb42Sjoerg   bool UsesFPIntrin : 1;
136*13fbcb42Sjoerg 
13706f32e7eSjoerg   /// Whether we make reference to a declaration that could be
13806f32e7eSjoerg   /// unavailable.
13906f32e7eSjoerg   bool HasPotentialAvailabilityViolations : 1;
14006f32e7eSjoerg 
14106f32e7eSjoerg   /// A flag that is set when parsing a method that must call super's
14206f32e7eSjoerg   /// implementation, such as \c -dealloc, \c -finalize, or any method marked
14306f32e7eSjoerg   /// with \c __attribute__((objc_requires_super)).
14406f32e7eSjoerg   bool ObjCShouldCallSuper : 1;
14506f32e7eSjoerg 
14606f32e7eSjoerg   /// True when this is a method marked as a designated initializer.
14706f32e7eSjoerg   bool ObjCIsDesignatedInit : 1;
14806f32e7eSjoerg 
14906f32e7eSjoerg   /// This starts true for a method marked as designated initializer and will
15006f32e7eSjoerg   /// be set to false if there is an invocation to a designated initializer of
15106f32e7eSjoerg   /// the super class.
15206f32e7eSjoerg   bool ObjCWarnForNoDesignatedInitChain : 1;
15306f32e7eSjoerg 
15406f32e7eSjoerg   /// True when this is an initializer method not marked as a designated
15506f32e7eSjoerg   /// initializer within a class that has at least one initializer marked as a
15606f32e7eSjoerg   /// designated initializer.
15706f32e7eSjoerg   bool ObjCIsSecondaryInit : 1;
15806f32e7eSjoerg 
15906f32e7eSjoerg   /// This starts true for a secondary initializer method and will be set to
16006f32e7eSjoerg   /// false if there is an invocation of an initializer on 'self'.
16106f32e7eSjoerg   bool ObjCWarnForNoInitDelegation : 1;
16206f32e7eSjoerg 
16306f32e7eSjoerg   /// True only when this function has not already built, or attempted
16406f32e7eSjoerg   /// to build, the initial and final coroutine suspend points
16506f32e7eSjoerg   bool NeedsCoroutineSuspends : 1;
16606f32e7eSjoerg 
16706f32e7eSjoerg   /// An enumeration represeting the kind of the first coroutine statement
16806f32e7eSjoerg   /// in the function. One of co_return, co_await, or co_yield.
16906f32e7eSjoerg   unsigned char FirstCoroutineStmtKind : 2;
17006f32e7eSjoerg 
17106f32e7eSjoerg   /// First coroutine statement in the current function.
17206f32e7eSjoerg   /// (ex co_return, co_await, co_yield)
17306f32e7eSjoerg   SourceLocation FirstCoroutineStmtLoc;
17406f32e7eSjoerg 
17506f32e7eSjoerg   /// First 'return' statement in the current function.
17606f32e7eSjoerg   SourceLocation FirstReturnLoc;
17706f32e7eSjoerg 
17806f32e7eSjoerg   /// First C++ 'try' statement in the current function.
17906f32e7eSjoerg   SourceLocation FirstCXXTryLoc;
18006f32e7eSjoerg 
18106f32e7eSjoerg   /// First SEH '__try' statement in the current function.
18206f32e7eSjoerg   SourceLocation FirstSEHTryLoc;
18306f32e7eSjoerg 
184*13fbcb42Sjoerg private:
18506f32e7eSjoerg   /// Used to determine if errors occurred in this function or block.
18606f32e7eSjoerg   DiagnosticErrorTrap ErrorTrap;
18706f32e7eSjoerg 
188*13fbcb42Sjoerg public:
18906f32e7eSjoerg   /// A SwitchStmt, along with a flag indicating if its list of case statements
19006f32e7eSjoerg   /// is incomplete (because we dropped an invalid one while parsing).
19106f32e7eSjoerg   using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>;
19206f32e7eSjoerg 
19306f32e7eSjoerg   /// SwitchStack - This is the current set of active switch statements in the
19406f32e7eSjoerg   /// block.
19506f32e7eSjoerg   SmallVector<SwitchInfo, 8> SwitchStack;
19606f32e7eSjoerg 
19706f32e7eSjoerg   /// The list of return statements that occur within the function or
19806f32e7eSjoerg   /// block, if there is any chance of applying the named return value
19906f32e7eSjoerg   /// optimization, or if we need to infer a return type.
20006f32e7eSjoerg   SmallVector<ReturnStmt*, 4> Returns;
20106f32e7eSjoerg 
20206f32e7eSjoerg   /// The promise object for this coroutine, if any.
20306f32e7eSjoerg   VarDecl *CoroutinePromise = nullptr;
20406f32e7eSjoerg 
20506f32e7eSjoerg   /// A mapping between the coroutine function parameters that were moved
20606f32e7eSjoerg   /// to the coroutine frame, and their move statements.
20706f32e7eSjoerg   llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves;
20806f32e7eSjoerg 
20906f32e7eSjoerg   /// The initial and final coroutine suspend points.
21006f32e7eSjoerg   std::pair<Stmt *, Stmt *> CoroutineSuspends;
21106f32e7eSjoerg 
21206f32e7eSjoerg   /// The stack of currently active compound stamement scopes in the
21306f32e7eSjoerg   /// function.
21406f32e7eSjoerg   SmallVector<CompoundScopeInfo, 4> CompoundScopes;
21506f32e7eSjoerg 
21606f32e7eSjoerg   /// The set of blocks that are introduced in this function.
21706f32e7eSjoerg   llvm::SmallPtrSet<const BlockDecl *, 1> Blocks;
21806f32e7eSjoerg 
21906f32e7eSjoerg   /// The set of __block variables that are introduced in this function.
22006f32e7eSjoerg   llvm::TinyPtrVector<VarDecl *> ByrefBlockVars;
22106f32e7eSjoerg 
22206f32e7eSjoerg   /// A list of PartialDiagnostics created but delayed within the
22306f32e7eSjoerg   /// current function scope.  These diagnostics are vetted for reachability
22406f32e7eSjoerg   /// prior to being emitted.
22506f32e7eSjoerg   SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
22606f32e7eSjoerg 
22706f32e7eSjoerg   /// A list of parameters which have the nonnull attribute and are
22806f32e7eSjoerg   /// modified in the function.
22906f32e7eSjoerg   llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
23006f32e7eSjoerg 
23106f32e7eSjoerg public:
23206f32e7eSjoerg   /// Represents a simple identification of a weak object.
23306f32e7eSjoerg   ///
23406f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
23506f32e7eSjoerg   ///
23606f32e7eSjoerg   /// This is used to determine if two weak accesses refer to the same object.
23706f32e7eSjoerg   /// Here are some examples of how various accesses are "profiled":
23806f32e7eSjoerg   ///
23906f32e7eSjoerg   /// Access Expression |     "Base" Decl     |          "Property" Decl
24006f32e7eSjoerg   /// :---------------: | :-----------------: | :------------------------------:
24106f32e7eSjoerg   /// self.property     | self (VarDecl)      | property (ObjCPropertyDecl)
24206f32e7eSjoerg   /// self.implicitProp | self (VarDecl)      | -implicitProp (ObjCMethodDecl)
24306f32e7eSjoerg   /// self->ivar.prop   | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl)
24406f32e7eSjoerg   /// cxxObj.obj.prop   | obj (FieldDecl)     | prop (ObjCPropertyDecl)
24506f32e7eSjoerg   /// [self foo].prop   | 0 (unknown)         | prop (ObjCPropertyDecl)
24606f32e7eSjoerg   /// self.prop1.prop2  | prop1 (ObjCPropertyDecl)    | prop2 (ObjCPropertyDecl)
24706f32e7eSjoerg   /// MyClass.prop      | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
24806f32e7eSjoerg   /// MyClass.foo.prop  | +foo (ObjCMethodDecl)       | -prop (ObjCPropertyDecl)
24906f32e7eSjoerg   /// weakVar           | 0 (known)           | weakVar (VarDecl)
25006f32e7eSjoerg   /// self->weakIvar    | self (VarDecl)      | weakIvar (ObjCIvarDecl)
25106f32e7eSjoerg   ///
25206f32e7eSjoerg   /// Objects are identified with only two Decls to make it reasonably fast to
25306f32e7eSjoerg   /// compare them.
25406f32e7eSjoerg   class WeakObjectProfileTy {
25506f32e7eSjoerg     /// The base object decl, as described in the class documentation.
25606f32e7eSjoerg     ///
25706f32e7eSjoerg     /// The extra flag is "true" if the Base and Property are enough to uniquely
25806f32e7eSjoerg     /// identify the object in memory.
25906f32e7eSjoerg     ///
26006f32e7eSjoerg     /// \sa isExactProfile()
26106f32e7eSjoerg     using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>;
26206f32e7eSjoerg     BaseInfoTy Base;
26306f32e7eSjoerg 
26406f32e7eSjoerg     /// The "property" decl, as described in the class documentation.
26506f32e7eSjoerg     ///
26606f32e7eSjoerg     /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the
26706f32e7eSjoerg     /// case of "implicit" properties (regular methods accessed via dot syntax).
26806f32e7eSjoerg     const NamedDecl *Property = nullptr;
26906f32e7eSjoerg 
27006f32e7eSjoerg     /// Used to find the proper base profile for a given base expression.
27106f32e7eSjoerg     static BaseInfoTy getBaseInfo(const Expr *BaseE);
27206f32e7eSjoerg 
27306f32e7eSjoerg     inline WeakObjectProfileTy();
27406f32e7eSjoerg     static inline WeakObjectProfileTy getSentinel();
27506f32e7eSjoerg 
27606f32e7eSjoerg   public:
27706f32e7eSjoerg     WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
27806f32e7eSjoerg     WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
27906f32e7eSjoerg     WeakObjectProfileTy(const DeclRefExpr *RE);
28006f32e7eSjoerg     WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
28106f32e7eSjoerg 
getBase()28206f32e7eSjoerg     const NamedDecl *getBase() const { return Base.getPointer(); }
getProperty()28306f32e7eSjoerg     const NamedDecl *getProperty() const { return Property; }
28406f32e7eSjoerg 
28506f32e7eSjoerg     /// Returns true if the object base specifies a known object in memory,
28606f32e7eSjoerg     /// rather than, say, an instance variable or property of another object.
28706f32e7eSjoerg     ///
28806f32e7eSjoerg     /// Note that this ignores the effects of aliasing; that is, \c foo.bar is
28906f32e7eSjoerg     /// considered an exact profile if \c foo is a local variable, even if
29006f32e7eSjoerg     /// another variable \c foo2 refers to the same object as \c foo.
29106f32e7eSjoerg     ///
29206f32e7eSjoerg     /// For increased precision, accesses with base variables that are
29306f32e7eSjoerg     /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to
29406f32e7eSjoerg     /// be exact, though this is not true for arbitrary variables
29506f32e7eSjoerg     /// (foo.prop1.prop2).
isExactProfile()29606f32e7eSjoerg     bool isExactProfile() const {
29706f32e7eSjoerg       return Base.getInt();
29806f32e7eSjoerg     }
29906f32e7eSjoerg 
30006f32e7eSjoerg     bool operator==(const WeakObjectProfileTy &Other) const {
30106f32e7eSjoerg       return Base == Other.Base && Property == Other.Property;
30206f32e7eSjoerg     }
30306f32e7eSjoerg 
30406f32e7eSjoerg     // For use in DenseMap.
30506f32e7eSjoerg     // We can't specialize the usual llvm::DenseMapInfo at the end of the file
30606f32e7eSjoerg     // because by that point the DenseMap in FunctionScopeInfo has already been
30706f32e7eSjoerg     // instantiated.
30806f32e7eSjoerg     class DenseMapInfo {
30906f32e7eSjoerg     public:
getEmptyKey()31006f32e7eSjoerg       static inline WeakObjectProfileTy getEmptyKey() {
31106f32e7eSjoerg         return WeakObjectProfileTy();
31206f32e7eSjoerg       }
31306f32e7eSjoerg 
getTombstoneKey()31406f32e7eSjoerg       static inline WeakObjectProfileTy getTombstoneKey() {
31506f32e7eSjoerg         return WeakObjectProfileTy::getSentinel();
31606f32e7eSjoerg       }
31706f32e7eSjoerg 
getHashValue(const WeakObjectProfileTy & Val)31806f32e7eSjoerg       static unsigned getHashValue(const WeakObjectProfileTy &Val) {
31906f32e7eSjoerg         using Pair = std::pair<BaseInfoTy, const NamedDecl *>;
32006f32e7eSjoerg 
32106f32e7eSjoerg         return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
32206f32e7eSjoerg                                                            Val.Property));
32306f32e7eSjoerg       }
32406f32e7eSjoerg 
isEqual(const WeakObjectProfileTy & LHS,const WeakObjectProfileTy & RHS)32506f32e7eSjoerg       static bool isEqual(const WeakObjectProfileTy &LHS,
32606f32e7eSjoerg                           const WeakObjectProfileTy &RHS) {
32706f32e7eSjoerg         return LHS == RHS;
32806f32e7eSjoerg       }
32906f32e7eSjoerg     };
33006f32e7eSjoerg   };
33106f32e7eSjoerg 
33206f32e7eSjoerg   /// Represents a single use of a weak object.
33306f32e7eSjoerg   ///
33406f32e7eSjoerg   /// Stores both the expression and whether the access is potentially unsafe
33506f32e7eSjoerg   /// (i.e. it could potentially be warned about).
33606f32e7eSjoerg   ///
33706f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
33806f32e7eSjoerg   class WeakUseTy {
33906f32e7eSjoerg     llvm::PointerIntPair<const Expr *, 1, bool> Rep;
34006f32e7eSjoerg 
34106f32e7eSjoerg   public:
WeakUseTy(const Expr * Use,bool IsRead)34206f32e7eSjoerg     WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
34306f32e7eSjoerg 
getUseExpr()34406f32e7eSjoerg     const Expr *getUseExpr() const { return Rep.getPointer(); }
isUnsafe()34506f32e7eSjoerg     bool isUnsafe() const { return Rep.getInt(); }
markSafe()34606f32e7eSjoerg     void markSafe() { Rep.setInt(false); }
34706f32e7eSjoerg 
34806f32e7eSjoerg     bool operator==(const WeakUseTy &Other) const {
34906f32e7eSjoerg       return Rep == Other.Rep;
35006f32e7eSjoerg     }
35106f32e7eSjoerg   };
35206f32e7eSjoerg 
35306f32e7eSjoerg   /// Used to collect uses of a particular weak object in a function body.
35406f32e7eSjoerg   ///
35506f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
35606f32e7eSjoerg   using WeakUseVector = SmallVector<WeakUseTy, 4>;
35706f32e7eSjoerg 
35806f32e7eSjoerg   /// Used to collect all uses of weak objects in a function body.
35906f32e7eSjoerg   ///
36006f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
36106f32e7eSjoerg   using WeakObjectUseMap =
36206f32e7eSjoerg       llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
36306f32e7eSjoerg                           WeakObjectProfileTy::DenseMapInfo>;
36406f32e7eSjoerg 
36506f32e7eSjoerg private:
36606f32e7eSjoerg   /// Used to collect all uses of weak objects in this function body.
36706f32e7eSjoerg   ///
36806f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
36906f32e7eSjoerg   WeakObjectUseMap WeakObjectUses;
37006f32e7eSjoerg 
37106f32e7eSjoerg protected:
37206f32e7eSjoerg   FunctionScopeInfo(const FunctionScopeInfo&) = default;
37306f32e7eSjoerg 
37406f32e7eSjoerg public:
FunctionScopeInfo(DiagnosticsEngine & Diag)37506f32e7eSjoerg   FunctionScopeInfo(DiagnosticsEngine &Diag)
37606f32e7eSjoerg       : Kind(SK_Function), HasBranchProtectedScope(false),
377*13fbcb42Sjoerg         HasBranchIntoScope(false), HasIndirectGoto(false), HasMustTail(false),
37806f32e7eSjoerg         HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false),
379*13fbcb42Sjoerg         HasFallthroughStmt(false), UsesFPIntrin(false),
380*13fbcb42Sjoerg         HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false),
381*13fbcb42Sjoerg         ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false),
382*13fbcb42Sjoerg         ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false),
383*13fbcb42Sjoerg         NeedsCoroutineSuspends(true), ErrorTrap(Diag) {}
38406f32e7eSjoerg 
38506f32e7eSjoerg   virtual ~FunctionScopeInfo();
38606f32e7eSjoerg 
387*13fbcb42Sjoerg   /// Determine whether an unrecoverable error has occurred within this
388*13fbcb42Sjoerg   /// function. Note that this may return false even if the function body is
389*13fbcb42Sjoerg   /// invalid, because the errors may be suppressed if they're caused by prior
390*13fbcb42Sjoerg   /// invalid declarations.
391*13fbcb42Sjoerg   ///
392*13fbcb42Sjoerg   /// FIXME: Migrate the caller of this to use containsErrors() instead once
393*13fbcb42Sjoerg   /// it's ready.
hasUnrecoverableErrorOccurred()394*13fbcb42Sjoerg   bool hasUnrecoverableErrorOccurred() const {
395*13fbcb42Sjoerg     return ErrorTrap.hasUnrecoverableErrorOccurred();
396*13fbcb42Sjoerg   }
397*13fbcb42Sjoerg 
39806f32e7eSjoerg   /// Record that a weak object was accessed.
39906f32e7eSjoerg   ///
40006f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
40106f32e7eSjoerg   template <typename ExprT>
40206f32e7eSjoerg   inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
40306f32e7eSjoerg 
40406f32e7eSjoerg   void recordUseOfWeak(const ObjCMessageExpr *Msg,
40506f32e7eSjoerg                        const ObjCPropertyDecl *Prop);
40606f32e7eSjoerg 
40706f32e7eSjoerg   /// Record that a given expression is a "safe" access of a weak object (e.g.
40806f32e7eSjoerg   /// assigning it to a strong variable.)
40906f32e7eSjoerg   ///
41006f32e7eSjoerg   /// Part of the implementation of -Wrepeated-use-of-weak.
41106f32e7eSjoerg   void markSafeWeakUse(const Expr *E);
41206f32e7eSjoerg 
getWeakObjectUses()41306f32e7eSjoerg   const WeakObjectUseMap &getWeakObjectUses() const {
41406f32e7eSjoerg     return WeakObjectUses;
41506f32e7eSjoerg   }
41606f32e7eSjoerg 
setHasBranchIntoScope()41706f32e7eSjoerg   void setHasBranchIntoScope() {
41806f32e7eSjoerg     HasBranchIntoScope = true;
41906f32e7eSjoerg   }
42006f32e7eSjoerg 
setHasBranchProtectedScope()42106f32e7eSjoerg   void setHasBranchProtectedScope() {
42206f32e7eSjoerg     HasBranchProtectedScope = true;
42306f32e7eSjoerg   }
42406f32e7eSjoerg 
setHasIndirectGoto()42506f32e7eSjoerg   void setHasIndirectGoto() {
42606f32e7eSjoerg     HasIndirectGoto = true;
42706f32e7eSjoerg   }
42806f32e7eSjoerg 
setHasMustTail()429*13fbcb42Sjoerg   void setHasMustTail() { HasMustTail = true; }
430*13fbcb42Sjoerg 
setHasDroppedStmt()43106f32e7eSjoerg   void setHasDroppedStmt() {
43206f32e7eSjoerg     HasDroppedStmt = true;
43306f32e7eSjoerg   }
43406f32e7eSjoerg 
setHasOMPDeclareReductionCombiner()43506f32e7eSjoerg   void setHasOMPDeclareReductionCombiner() {
43606f32e7eSjoerg     HasOMPDeclareReductionCombiner = true;
43706f32e7eSjoerg   }
43806f32e7eSjoerg 
setHasFallthroughStmt()43906f32e7eSjoerg   void setHasFallthroughStmt() {
44006f32e7eSjoerg     HasFallthroughStmt = true;
44106f32e7eSjoerg   }
44206f32e7eSjoerg 
setUsesFPIntrin()443*13fbcb42Sjoerg   void setUsesFPIntrin() {
444*13fbcb42Sjoerg     UsesFPIntrin = true;
445*13fbcb42Sjoerg   }
446*13fbcb42Sjoerg 
setHasCXXTry(SourceLocation TryLoc)44706f32e7eSjoerg   void setHasCXXTry(SourceLocation TryLoc) {
44806f32e7eSjoerg     setHasBranchProtectedScope();
44906f32e7eSjoerg     FirstCXXTryLoc = TryLoc;
45006f32e7eSjoerg   }
45106f32e7eSjoerg 
setHasSEHTry(SourceLocation TryLoc)45206f32e7eSjoerg   void setHasSEHTry(SourceLocation TryLoc) {
45306f32e7eSjoerg     setHasBranchProtectedScope();
45406f32e7eSjoerg     FirstSEHTryLoc = TryLoc;
45506f32e7eSjoerg   }
45606f32e7eSjoerg 
NeedsScopeChecking()45706f32e7eSjoerg   bool NeedsScopeChecking() const {
458*13fbcb42Sjoerg     return !HasDroppedStmt && (HasIndirectGoto || HasMustTail ||
45906f32e7eSjoerg                                (HasBranchProtectedScope && HasBranchIntoScope));
46006f32e7eSjoerg   }
46106f32e7eSjoerg 
46206f32e7eSjoerg   // Add a block introduced in this function.
addBlock(const BlockDecl * BD)46306f32e7eSjoerg   void addBlock(const BlockDecl *BD) {
46406f32e7eSjoerg     Blocks.insert(BD);
46506f32e7eSjoerg   }
46606f32e7eSjoerg 
46706f32e7eSjoerg   // Add a __block variable introduced in this function.
addByrefBlockVar(VarDecl * VD)46806f32e7eSjoerg   void addByrefBlockVar(VarDecl *VD) {
46906f32e7eSjoerg     ByrefBlockVars.push_back(VD);
47006f32e7eSjoerg   }
47106f32e7eSjoerg 
isCoroutine()47206f32e7eSjoerg   bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); }
47306f32e7eSjoerg 
setFirstCoroutineStmt(SourceLocation Loc,StringRef Keyword)47406f32e7eSjoerg   void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) {
47506f32e7eSjoerg     assert(FirstCoroutineStmtLoc.isInvalid() &&
47606f32e7eSjoerg                    "first coroutine statement location already set");
47706f32e7eSjoerg     FirstCoroutineStmtLoc = Loc;
47806f32e7eSjoerg     FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword)
47906f32e7eSjoerg             .Case("co_return", 0)
48006f32e7eSjoerg             .Case("co_await", 1)
48106f32e7eSjoerg             .Case("co_yield", 2);
48206f32e7eSjoerg   }
48306f32e7eSjoerg 
getFirstCoroutineStmtKeyword()48406f32e7eSjoerg   StringRef getFirstCoroutineStmtKeyword() const {
48506f32e7eSjoerg     assert(FirstCoroutineStmtLoc.isValid()
48606f32e7eSjoerg                    && "no coroutine statement available");
48706f32e7eSjoerg     switch (FirstCoroutineStmtKind) {
48806f32e7eSjoerg     case 0: return "co_return";
48906f32e7eSjoerg     case 1: return "co_await";
49006f32e7eSjoerg     case 2: return "co_yield";
49106f32e7eSjoerg     default:
49206f32e7eSjoerg       llvm_unreachable("FirstCoroutineStmtKind has an invalid value");
49306f32e7eSjoerg     };
49406f32e7eSjoerg   }
49506f32e7eSjoerg 
49606f32e7eSjoerg   void setNeedsCoroutineSuspends(bool value = true) {
49706f32e7eSjoerg     assert((!value || CoroutineSuspends.first == nullptr) &&
49806f32e7eSjoerg             "we already have valid suspend points");
49906f32e7eSjoerg     NeedsCoroutineSuspends = value;
50006f32e7eSjoerg   }
50106f32e7eSjoerg 
hasInvalidCoroutineSuspends()50206f32e7eSjoerg   bool hasInvalidCoroutineSuspends() const {
50306f32e7eSjoerg     return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr;
50406f32e7eSjoerg   }
50506f32e7eSjoerg 
setCoroutineSuspends(Stmt * Initial,Stmt * Final)50606f32e7eSjoerg   void setCoroutineSuspends(Stmt *Initial, Stmt *Final) {
50706f32e7eSjoerg     assert(Initial && Final && "suspend points cannot be null");
50806f32e7eSjoerg     assert(CoroutineSuspends.first == nullptr && "suspend points already set");
50906f32e7eSjoerg     NeedsCoroutineSuspends = false;
51006f32e7eSjoerg     CoroutineSuspends.first = Initial;
51106f32e7eSjoerg     CoroutineSuspends.second = Final;
51206f32e7eSjoerg   }
51306f32e7eSjoerg 
51406f32e7eSjoerg   /// Clear out the information in this function scope, making it
51506f32e7eSjoerg   /// suitable for reuse.
51606f32e7eSjoerg   void Clear();
51706f32e7eSjoerg 
isPlainFunction()51806f32e7eSjoerg   bool isPlainFunction() const { return Kind == SK_Function; }
51906f32e7eSjoerg };
52006f32e7eSjoerg 
52106f32e7eSjoerg class Capture {
52206f32e7eSjoerg   // There are three categories of capture: capturing 'this', capturing
52306f32e7eSjoerg   // local variables, and C++1y initialized captures (which can have an
52406f32e7eSjoerg   // arbitrary initializer, and don't really capture in the traditional
52506f32e7eSjoerg   // sense at all).
52606f32e7eSjoerg   //
52706f32e7eSjoerg   // There are three ways to capture a local variable:
52806f32e7eSjoerg   //  - capture by copy in the C++11 sense,
52906f32e7eSjoerg   //  - capture by reference in the C++11 sense, and
53006f32e7eSjoerg   //  - __block capture.
53106f32e7eSjoerg   // Lambdas explicitly specify capture by copy or capture by reference.
53206f32e7eSjoerg   // For blocks, __block capture applies to variables with that annotation,
53306f32e7eSjoerg   // variables of reference type are captured by reference, and other
53406f32e7eSjoerg   // variables are captured by copy.
53506f32e7eSjoerg   enum CaptureKind {
53606f32e7eSjoerg     Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
53706f32e7eSjoerg   };
53806f32e7eSjoerg 
53906f32e7eSjoerg   union {
54006f32e7eSjoerg     /// If Kind == Cap_VLA, the captured type.
54106f32e7eSjoerg     const VariableArrayType *CapturedVLA;
54206f32e7eSjoerg 
54306f32e7eSjoerg     /// Otherwise, the captured variable (if any).
54406f32e7eSjoerg     VarDecl *CapturedVar;
54506f32e7eSjoerg   };
54606f32e7eSjoerg 
54706f32e7eSjoerg   /// The source location at which the first capture occurred.
54806f32e7eSjoerg   SourceLocation Loc;
54906f32e7eSjoerg 
55006f32e7eSjoerg   /// The location of the ellipsis that expands a parameter pack.
55106f32e7eSjoerg   SourceLocation EllipsisLoc;
55206f32e7eSjoerg 
55306f32e7eSjoerg   /// The type as it was captured, which is the type of the non-static data
55406f32e7eSjoerg   /// member that would hold the capture.
55506f32e7eSjoerg   QualType CaptureType;
55606f32e7eSjoerg 
55706f32e7eSjoerg   /// The CaptureKind of this capture.
55806f32e7eSjoerg   unsigned Kind : 2;
55906f32e7eSjoerg 
56006f32e7eSjoerg   /// Whether this is a nested capture (a capture of an enclosing capturing
56106f32e7eSjoerg   /// scope's capture).
56206f32e7eSjoerg   unsigned Nested : 1;
56306f32e7eSjoerg 
56406f32e7eSjoerg   /// Whether this is a capture of '*this'.
56506f32e7eSjoerg   unsigned CapturesThis : 1;
56606f32e7eSjoerg 
56706f32e7eSjoerg   /// Whether an explicit capture has been odr-used in the body of the
56806f32e7eSjoerg   /// lambda.
56906f32e7eSjoerg   unsigned ODRUsed : 1;
57006f32e7eSjoerg 
57106f32e7eSjoerg   /// Whether an explicit capture has been non-odr-used in the body of
57206f32e7eSjoerg   /// the lambda.
57306f32e7eSjoerg   unsigned NonODRUsed : 1;
57406f32e7eSjoerg 
57506f32e7eSjoerg   /// Whether the capture is invalid (a capture was required but the entity is
57606f32e7eSjoerg   /// non-capturable).
57706f32e7eSjoerg   unsigned Invalid : 1;
57806f32e7eSjoerg 
57906f32e7eSjoerg public:
Capture(VarDecl * Var,bool Block,bool ByRef,bool IsNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,bool Invalid)58006f32e7eSjoerg   Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
58106f32e7eSjoerg           SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType,
58206f32e7eSjoerg           bool Invalid)
58306f32e7eSjoerg       : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc),
58406f32e7eSjoerg         CaptureType(CaptureType),
58506f32e7eSjoerg         Kind(Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy),
58606f32e7eSjoerg         Nested(IsNested), CapturesThis(false), ODRUsed(false),
58706f32e7eSjoerg         NonODRUsed(false), Invalid(Invalid) {}
58806f32e7eSjoerg 
58906f32e7eSjoerg   enum IsThisCapture { ThisCapture };
Capture(IsThisCapture,bool IsNested,SourceLocation Loc,QualType CaptureType,const bool ByCopy,bool Invalid)59006f32e7eSjoerg   Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
59106f32e7eSjoerg           QualType CaptureType, const bool ByCopy, bool Invalid)
59206f32e7eSjoerg       : Loc(Loc), CaptureType(CaptureType),
59306f32e7eSjoerg         Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested),
59406f32e7eSjoerg         CapturesThis(true), ODRUsed(false), NonODRUsed(false),
59506f32e7eSjoerg         Invalid(Invalid) {}
59606f32e7eSjoerg 
59706f32e7eSjoerg   enum IsVLACapture { VLACapture };
Capture(IsVLACapture,const VariableArrayType * VLA,bool IsNested,SourceLocation Loc,QualType CaptureType)59806f32e7eSjoerg   Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested,
59906f32e7eSjoerg           SourceLocation Loc, QualType CaptureType)
60006f32e7eSjoerg       : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA),
60106f32e7eSjoerg         Nested(IsNested), CapturesThis(false), ODRUsed(false),
60206f32e7eSjoerg         NonODRUsed(false), Invalid(false) {}
60306f32e7eSjoerg 
isThisCapture()60406f32e7eSjoerg   bool isThisCapture() const { return CapturesThis; }
isVariableCapture()60506f32e7eSjoerg   bool isVariableCapture() const {
60606f32e7eSjoerg     return !isThisCapture() && !isVLATypeCapture();
60706f32e7eSjoerg   }
60806f32e7eSjoerg 
isCopyCapture()60906f32e7eSjoerg   bool isCopyCapture() const { return Kind == Cap_ByCopy; }
isReferenceCapture()61006f32e7eSjoerg   bool isReferenceCapture() const { return Kind == Cap_ByRef; }
isBlockCapture()61106f32e7eSjoerg   bool isBlockCapture() const { return Kind == Cap_Block; }
isVLATypeCapture()61206f32e7eSjoerg   bool isVLATypeCapture() const { return Kind == Cap_VLA; }
61306f32e7eSjoerg 
isNested()61406f32e7eSjoerg   bool isNested() const { return Nested; }
61506f32e7eSjoerg 
isInvalid()61606f32e7eSjoerg   bool isInvalid() const { return Invalid; }
61706f32e7eSjoerg 
61806f32e7eSjoerg   /// Determine whether this capture is an init-capture.
61906f32e7eSjoerg   bool isInitCapture() const;
62006f32e7eSjoerg 
isODRUsed()62106f32e7eSjoerg   bool isODRUsed() const { return ODRUsed; }
isNonODRUsed()62206f32e7eSjoerg   bool isNonODRUsed() const { return NonODRUsed; }
markUsed(bool IsODRUse)62306f32e7eSjoerg   void markUsed(bool IsODRUse) {
62406f32e7eSjoerg     if (IsODRUse)
62506f32e7eSjoerg       ODRUsed = true;
62606f32e7eSjoerg     else
62706f32e7eSjoerg       NonODRUsed = true;
62806f32e7eSjoerg   }
62906f32e7eSjoerg 
getVariable()63006f32e7eSjoerg   VarDecl *getVariable() const {
63106f32e7eSjoerg     assert(isVariableCapture());
63206f32e7eSjoerg     return CapturedVar;
63306f32e7eSjoerg   }
63406f32e7eSjoerg 
getCapturedVLAType()63506f32e7eSjoerg   const VariableArrayType *getCapturedVLAType() const {
63606f32e7eSjoerg     assert(isVLATypeCapture());
63706f32e7eSjoerg     return CapturedVLA;
63806f32e7eSjoerg   }
63906f32e7eSjoerg 
64006f32e7eSjoerg   /// Retrieve the location at which this variable was captured.
getLocation()64106f32e7eSjoerg   SourceLocation getLocation() const { return Loc; }
64206f32e7eSjoerg 
64306f32e7eSjoerg   /// Retrieve the source location of the ellipsis, whose presence
64406f32e7eSjoerg   /// indicates that the capture is a pack expansion.
getEllipsisLoc()64506f32e7eSjoerg   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
64606f32e7eSjoerg 
64706f32e7eSjoerg   /// Retrieve the capture type for this capture, which is effectively
64806f32e7eSjoerg   /// the type of the non-static data member in the lambda/block structure
64906f32e7eSjoerg   /// that would store this capture.
getCaptureType()65006f32e7eSjoerg   QualType getCaptureType() const { return CaptureType; }
65106f32e7eSjoerg };
65206f32e7eSjoerg 
65306f32e7eSjoerg class CapturingScopeInfo : public FunctionScopeInfo {
65406f32e7eSjoerg protected:
65506f32e7eSjoerg   CapturingScopeInfo(const CapturingScopeInfo&) = default;
65606f32e7eSjoerg 
65706f32e7eSjoerg public:
65806f32e7eSjoerg   enum ImplicitCaptureStyle {
65906f32e7eSjoerg     ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
66006f32e7eSjoerg     ImpCap_CapturedRegion
66106f32e7eSjoerg   };
66206f32e7eSjoerg 
66306f32e7eSjoerg   ImplicitCaptureStyle ImpCaptureStyle;
66406f32e7eSjoerg 
CapturingScopeInfo(DiagnosticsEngine & Diag,ImplicitCaptureStyle Style)66506f32e7eSjoerg   CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
66606f32e7eSjoerg       : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
66706f32e7eSjoerg 
66806f32e7eSjoerg   /// CaptureMap - A map of captured variables to (index+1) into Captures.
66906f32e7eSjoerg   llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
67006f32e7eSjoerg 
67106f32e7eSjoerg   /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
67206f32e7eSjoerg   /// zero if 'this' is not captured.
67306f32e7eSjoerg   unsigned CXXThisCaptureIndex = 0;
67406f32e7eSjoerg 
67506f32e7eSjoerg   /// Captures - The captures.
67606f32e7eSjoerg   SmallVector<Capture, 4> Captures;
67706f32e7eSjoerg 
67806f32e7eSjoerg   /// - Whether the target type of return statements in this context
67906f32e7eSjoerg   /// is deduced (e.g. a lambda or block with omitted return type).
68006f32e7eSjoerg   bool HasImplicitReturnType = false;
68106f32e7eSjoerg 
68206f32e7eSjoerg   /// ReturnType - The target type of return statements in this context,
68306f32e7eSjoerg   /// or null if unknown.
68406f32e7eSjoerg   QualType ReturnType;
68506f32e7eSjoerg 
addCapture(VarDecl * Var,bool isBlock,bool isByref,bool isNested,SourceLocation Loc,SourceLocation EllipsisLoc,QualType CaptureType,bool Invalid)68606f32e7eSjoerg   void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
68706f32e7eSjoerg                   SourceLocation Loc, SourceLocation EllipsisLoc,
68806f32e7eSjoerg                   QualType CaptureType, bool Invalid) {
68906f32e7eSjoerg     Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
69006f32e7eSjoerg                                EllipsisLoc, CaptureType, Invalid));
69106f32e7eSjoerg     CaptureMap[Var] = Captures.size();
69206f32e7eSjoerg   }
69306f32e7eSjoerg 
addVLATypeCapture(SourceLocation Loc,const VariableArrayType * VLAType,QualType CaptureType)69406f32e7eSjoerg   void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType,
69506f32e7eSjoerg                          QualType CaptureType) {
69606f32e7eSjoerg     Captures.push_back(Capture(Capture::VLACapture, VLAType,
69706f32e7eSjoerg                                /*FIXME: IsNested*/ false, Loc, CaptureType));
69806f32e7eSjoerg   }
69906f32e7eSjoerg 
70006f32e7eSjoerg   void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
70106f32e7eSjoerg                       bool ByCopy);
70206f32e7eSjoerg 
70306f32e7eSjoerg   /// Determine whether the C++ 'this' is captured.
isCXXThisCaptured()70406f32e7eSjoerg   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
70506f32e7eSjoerg 
70606f32e7eSjoerg   /// Retrieve the capture of C++ 'this', if it has been captured.
getCXXThisCapture()70706f32e7eSjoerg   Capture &getCXXThisCapture() {
70806f32e7eSjoerg     assert(isCXXThisCaptured() && "this has not been captured");
70906f32e7eSjoerg     return Captures[CXXThisCaptureIndex - 1];
71006f32e7eSjoerg   }
71106f32e7eSjoerg 
71206f32e7eSjoerg   /// Determine whether the given variable has been captured.
isCaptured(VarDecl * Var)71306f32e7eSjoerg   bool isCaptured(VarDecl *Var) const {
71406f32e7eSjoerg     return CaptureMap.count(Var);
71506f32e7eSjoerg   }
71606f32e7eSjoerg 
71706f32e7eSjoerg   /// Determine whether the given variable-array type has been captured.
71806f32e7eSjoerg   bool isVLATypeCaptured(const VariableArrayType *VAT) const;
71906f32e7eSjoerg 
72006f32e7eSjoerg   /// Retrieve the capture of the given variable, if it has been
72106f32e7eSjoerg   /// captured already.
getCapture(VarDecl * Var)72206f32e7eSjoerg   Capture &getCapture(VarDecl *Var) {
72306f32e7eSjoerg     assert(isCaptured(Var) && "Variable has not been captured");
72406f32e7eSjoerg     return Captures[CaptureMap[Var] - 1];
72506f32e7eSjoerg   }
72606f32e7eSjoerg 
getCapture(VarDecl * Var)72706f32e7eSjoerg   const Capture &getCapture(VarDecl *Var) const {
72806f32e7eSjoerg     llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known
72906f32e7eSjoerg       = CaptureMap.find(Var);
73006f32e7eSjoerg     assert(Known != CaptureMap.end() && "Variable has not been captured");
73106f32e7eSjoerg     return Captures[Known->second - 1];
73206f32e7eSjoerg   }
73306f32e7eSjoerg 
classof(const FunctionScopeInfo * FSI)73406f32e7eSjoerg   static bool classof(const FunctionScopeInfo *FSI) {
73506f32e7eSjoerg     return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
73606f32e7eSjoerg                                  || FSI->Kind == SK_CapturedRegion;
73706f32e7eSjoerg   }
73806f32e7eSjoerg };
73906f32e7eSjoerg 
74006f32e7eSjoerg /// Retains information about a block that is currently being parsed.
74106f32e7eSjoerg class BlockScopeInfo final : public CapturingScopeInfo {
74206f32e7eSjoerg public:
74306f32e7eSjoerg   BlockDecl *TheDecl;
74406f32e7eSjoerg 
74506f32e7eSjoerg   /// TheScope - This is the scope for the block itself, which contains
74606f32e7eSjoerg   /// arguments etc.
74706f32e7eSjoerg   Scope *TheScope;
74806f32e7eSjoerg 
74906f32e7eSjoerg   /// BlockType - The function type of the block, if one was given.
75006f32e7eSjoerg   /// Its return type may be BuiltinType::Dependent.
75106f32e7eSjoerg   QualType FunctionType;
75206f32e7eSjoerg 
BlockScopeInfo(DiagnosticsEngine & Diag,Scope * BlockScope,BlockDecl * Block)75306f32e7eSjoerg   BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
75406f32e7eSjoerg       : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
75506f32e7eSjoerg         TheScope(BlockScope) {
75606f32e7eSjoerg     Kind = SK_Block;
75706f32e7eSjoerg   }
75806f32e7eSjoerg 
75906f32e7eSjoerg   ~BlockScopeInfo() override;
76006f32e7eSjoerg 
classof(const FunctionScopeInfo * FSI)76106f32e7eSjoerg   static bool classof(const FunctionScopeInfo *FSI) {
76206f32e7eSjoerg     return FSI->Kind == SK_Block;
76306f32e7eSjoerg   }
76406f32e7eSjoerg };
76506f32e7eSjoerg 
76606f32e7eSjoerg /// Retains information about a captured region.
76706f32e7eSjoerg class CapturedRegionScopeInfo final : public CapturingScopeInfo {
76806f32e7eSjoerg public:
76906f32e7eSjoerg   /// The CapturedDecl for this statement.
77006f32e7eSjoerg   CapturedDecl *TheCapturedDecl;
77106f32e7eSjoerg 
77206f32e7eSjoerg   /// The captured record type.
77306f32e7eSjoerg   RecordDecl *TheRecordDecl;
77406f32e7eSjoerg 
77506f32e7eSjoerg   /// This is the enclosing scope of the captured region.
77606f32e7eSjoerg   Scope *TheScope;
77706f32e7eSjoerg 
77806f32e7eSjoerg   /// The implicit parameter for the captured variables.
77906f32e7eSjoerg   ImplicitParamDecl *ContextParam;
78006f32e7eSjoerg 
78106f32e7eSjoerg   /// The kind of captured region.
78206f32e7eSjoerg   unsigned short CapRegionKind;
78306f32e7eSjoerg 
78406f32e7eSjoerg   unsigned short OpenMPLevel;
78506f32e7eSjoerg   unsigned short OpenMPCaptureLevel;
78606f32e7eSjoerg 
CapturedRegionScopeInfo(DiagnosticsEngine & Diag,Scope * S,CapturedDecl * CD,RecordDecl * RD,ImplicitParamDecl * Context,CapturedRegionKind K,unsigned OpenMPLevel,unsigned OpenMPCaptureLevel)78706f32e7eSjoerg   CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
78806f32e7eSjoerg                           RecordDecl *RD, ImplicitParamDecl *Context,
78906f32e7eSjoerg                           CapturedRegionKind K, unsigned OpenMPLevel,
79006f32e7eSjoerg                           unsigned OpenMPCaptureLevel)
79106f32e7eSjoerg       : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
79206f32e7eSjoerg         TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
79306f32e7eSjoerg         ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel),
79406f32e7eSjoerg         OpenMPCaptureLevel(OpenMPCaptureLevel) {
79506f32e7eSjoerg     Kind = SK_CapturedRegion;
79606f32e7eSjoerg   }
79706f32e7eSjoerg 
79806f32e7eSjoerg   ~CapturedRegionScopeInfo() override;
79906f32e7eSjoerg 
80006f32e7eSjoerg   /// A descriptive name for the kind of captured region this is.
getRegionName()80106f32e7eSjoerg   StringRef getRegionName() const {
80206f32e7eSjoerg     switch (CapRegionKind) {
80306f32e7eSjoerg     case CR_Default:
80406f32e7eSjoerg       return "default captured statement";
80506f32e7eSjoerg     case CR_ObjCAtFinally:
80606f32e7eSjoerg       return "Objective-C @finally statement";
80706f32e7eSjoerg     case CR_OpenMP:
80806f32e7eSjoerg       return "OpenMP region";
80906f32e7eSjoerg     }
81006f32e7eSjoerg     llvm_unreachable("Invalid captured region kind!");
81106f32e7eSjoerg   }
81206f32e7eSjoerg 
classof(const FunctionScopeInfo * FSI)81306f32e7eSjoerg   static bool classof(const FunctionScopeInfo *FSI) {
81406f32e7eSjoerg     return FSI->Kind == SK_CapturedRegion;
81506f32e7eSjoerg   }
81606f32e7eSjoerg };
81706f32e7eSjoerg 
818*13fbcb42Sjoerg class LambdaScopeInfo final :
819*13fbcb42Sjoerg     public CapturingScopeInfo, public InventedTemplateParameterInfo {
82006f32e7eSjoerg public:
82106f32e7eSjoerg   /// The class that describes the lambda.
82206f32e7eSjoerg   CXXRecordDecl *Lambda = nullptr;
82306f32e7eSjoerg 
82406f32e7eSjoerg   /// The lambda's compiler-generated \c operator().
82506f32e7eSjoerg   CXXMethodDecl *CallOperator = nullptr;
82606f32e7eSjoerg 
82706f32e7eSjoerg   /// Source range covering the lambda introducer [...].
82806f32e7eSjoerg   SourceRange IntroducerRange;
82906f32e7eSjoerg 
83006f32e7eSjoerg   /// Source location of the '&' or '=' specifying the default capture
83106f32e7eSjoerg   /// type, if any.
83206f32e7eSjoerg   SourceLocation CaptureDefaultLoc;
83306f32e7eSjoerg 
83406f32e7eSjoerg   /// The number of captures in the \c Captures list that are
83506f32e7eSjoerg   /// explicit captures.
83606f32e7eSjoerg   unsigned NumExplicitCaptures = 0;
83706f32e7eSjoerg 
83806f32e7eSjoerg   /// Whether this is a mutable lambda.
83906f32e7eSjoerg   bool Mutable = false;
84006f32e7eSjoerg 
84106f32e7eSjoerg   /// Whether the (empty) parameter list is explicit.
84206f32e7eSjoerg   bool ExplicitParams = false;
84306f32e7eSjoerg 
84406f32e7eSjoerg   /// Whether any of the capture expressions requires cleanups.
84506f32e7eSjoerg   CleanupInfo Cleanup;
84606f32e7eSjoerg 
84706f32e7eSjoerg   /// Whether the lambda contains an unexpanded parameter pack.
84806f32e7eSjoerg   bool ContainsUnexpandedParameterPack = false;
84906f32e7eSjoerg 
85006f32e7eSjoerg   /// Packs introduced by this lambda, if any.
85106f32e7eSjoerg   SmallVector<NamedDecl*, 4> LocalPacks;
85206f32e7eSjoerg 
85306f32e7eSjoerg   /// Source range covering the explicit template parameter list (if it exists).
85406f32e7eSjoerg   SourceRange ExplicitTemplateParamsRange;
85506f32e7eSjoerg 
856*13fbcb42Sjoerg   /// The requires-clause immediately following the explicit template parameter
857*13fbcb42Sjoerg   /// list, if any. (Note that there may be another requires-clause included as
858*13fbcb42Sjoerg   /// part of the lambda-declarator.)
859*13fbcb42Sjoerg   ExprResult RequiresClause;
86006f32e7eSjoerg 
86106f32e7eSjoerg   /// If this is a generic lambda, and the template parameter
86206f32e7eSjoerg   /// list has been created (from the TemplateParams) then store
86306f32e7eSjoerg   /// a reference to it (cache it to avoid reconstructing it).
86406f32e7eSjoerg   TemplateParameterList *GLTemplateParameterList = nullptr;
86506f32e7eSjoerg 
86606f32e7eSjoerg   /// Contains all variable-referring-expressions (i.e. DeclRefExprs
86706f32e7eSjoerg   ///  or MemberExprs) that refer to local variables in a generic lambda
86806f32e7eSjoerg   ///  or a lambda in a potentially-evaluated-if-used context.
86906f32e7eSjoerg   ///
87006f32e7eSjoerg   ///  Potentially capturable variables of a nested lambda that might need
87106f32e7eSjoerg   ///   to be captured by the lambda are housed here.
87206f32e7eSjoerg   ///  This is specifically useful for generic lambdas or
87306f32e7eSjoerg   ///  lambdas within a potentially evaluated-if-used context.
87406f32e7eSjoerg   ///  If an enclosing variable is named in an expression of a lambda nested
87506f32e7eSjoerg   ///  within a generic lambda, we don't always know know whether the variable
87606f32e7eSjoerg   ///  will truly be odr-used (i.e. need to be captured) by that nested lambda,
87706f32e7eSjoerg   ///  until its instantiation. But we still need to capture it in the
87806f32e7eSjoerg   ///  enclosing lambda if all intervening lambdas can capture the variable.
87906f32e7eSjoerg   llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
88006f32e7eSjoerg 
88106f32e7eSjoerg   /// Contains all variable-referring-expressions that refer
88206f32e7eSjoerg   ///  to local variables that are usable as constant expressions and
88306f32e7eSjoerg   ///  do not involve an odr-use (they may still need to be captured
88406f32e7eSjoerg   ///  if the enclosing full-expression is instantiation dependent).
88506f32e7eSjoerg   llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs;
88606f32e7eSjoerg 
88706f32e7eSjoerg   /// A map of explicit capture indices to their introducer source ranges.
88806f32e7eSjoerg   llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges;
88906f32e7eSjoerg 
89006f32e7eSjoerg   /// Contains all of the variables defined in this lambda that shadow variables
89106f32e7eSjoerg   /// that were defined in parent contexts. Used to avoid warnings when the
89206f32e7eSjoerg   /// shadowed variables are uncaptured by this lambda.
89306f32e7eSjoerg   struct ShadowedOuterDecl {
89406f32e7eSjoerg     const VarDecl *VD;
89506f32e7eSjoerg     const VarDecl *ShadowedDecl;
89606f32e7eSjoerg   };
89706f32e7eSjoerg   llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls;
89806f32e7eSjoerg 
89906f32e7eSjoerg   SourceLocation PotentialThisCaptureLocation;
90006f32e7eSjoerg 
LambdaScopeInfo(DiagnosticsEngine & Diag)90106f32e7eSjoerg   LambdaScopeInfo(DiagnosticsEngine &Diag)
90206f32e7eSjoerg       : CapturingScopeInfo(Diag, ImpCap_None) {
90306f32e7eSjoerg     Kind = SK_Lambda;
90406f32e7eSjoerg   }
90506f32e7eSjoerg 
90606f32e7eSjoerg   /// Note when all explicit captures have been added.
finishedExplicitCaptures()90706f32e7eSjoerg   void finishedExplicitCaptures() {
90806f32e7eSjoerg     NumExplicitCaptures = Captures.size();
90906f32e7eSjoerg   }
91006f32e7eSjoerg 
classof(const FunctionScopeInfo * FSI)91106f32e7eSjoerg   static bool classof(const FunctionScopeInfo *FSI) {
91206f32e7eSjoerg     return FSI->Kind == SK_Lambda;
91306f32e7eSjoerg   }
91406f32e7eSjoerg 
91506f32e7eSjoerg   /// Is this scope known to be for a generic lambda? (This will be false until
91606f32e7eSjoerg   /// we parse a template parameter list or the first 'auto'-typed parameter).
isGenericLambda()91706f32e7eSjoerg   bool isGenericLambda() const {
91806f32e7eSjoerg     return !TemplateParams.empty() || GLTemplateParameterList;
91906f32e7eSjoerg   }
92006f32e7eSjoerg 
92106f32e7eSjoerg   /// Add a variable that might potentially be captured by the
92206f32e7eSjoerg   /// lambda and therefore the enclosing lambdas.
92306f32e7eSjoerg   ///
92406f32e7eSjoerg   /// This is also used by enclosing lambda's to speculatively capture
92506f32e7eSjoerg   /// variables that nested lambda's - depending on their enclosing
92606f32e7eSjoerg   /// specialization - might need to capture.
92706f32e7eSjoerg   /// Consider:
92806f32e7eSjoerg   /// void f(int, int); <-- don't capture
92906f32e7eSjoerg   /// void f(const int&, double); <-- capture
93006f32e7eSjoerg   /// void foo() {
93106f32e7eSjoerg   ///   const int x = 10;
93206f32e7eSjoerg   ///   auto L = [=](auto a) { // capture 'x'
93306f32e7eSjoerg   ///      return [=](auto b) {
93406f32e7eSjoerg   ///        f(x, a);  // we may or may not need to capture 'x'
93506f32e7eSjoerg   ///      };
93606f32e7eSjoerg   ///   };
93706f32e7eSjoerg   /// }
addPotentialCapture(Expr * VarExpr)93806f32e7eSjoerg   void addPotentialCapture(Expr *VarExpr) {
93906f32e7eSjoerg     assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr) ||
94006f32e7eSjoerg            isa<FunctionParmPackExpr>(VarExpr));
94106f32e7eSjoerg     PotentiallyCapturingExprs.push_back(VarExpr);
94206f32e7eSjoerg   }
94306f32e7eSjoerg 
addPotentialThisCapture(SourceLocation Loc)94406f32e7eSjoerg   void addPotentialThisCapture(SourceLocation Loc) {
94506f32e7eSjoerg     PotentialThisCaptureLocation = Loc;
94606f32e7eSjoerg   }
94706f32e7eSjoerg 
hasPotentialThisCapture()94806f32e7eSjoerg   bool hasPotentialThisCapture() const {
94906f32e7eSjoerg     return PotentialThisCaptureLocation.isValid();
95006f32e7eSjoerg   }
95106f32e7eSjoerg 
95206f32e7eSjoerg   /// Mark a variable's reference in a lambda as non-odr using.
95306f32e7eSjoerg   ///
95406f32e7eSjoerg   /// For generic lambdas, if a variable is named in a potentially evaluated
95506f32e7eSjoerg   /// expression, where the enclosing full expression is dependent then we
95606f32e7eSjoerg   /// must capture the variable (given a default capture).
95706f32e7eSjoerg   /// This is accomplished by recording all references to variables
95806f32e7eSjoerg   /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
95906f32e7eSjoerg   /// PotentialCaptures. All such variables have to be captured by that lambda,
96006f32e7eSjoerg   /// except for as described below.
96106f32e7eSjoerg   /// If that variable is usable as a constant expression and is named in a
96206f32e7eSjoerg   /// manner that does not involve its odr-use (e.g. undergoes
96306f32e7eSjoerg   /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the
96406f32e7eSjoerg   /// act of analyzing the enclosing full expression (ActOnFinishFullExpr)
96506f32e7eSjoerg   /// if we can determine that the full expression is not instantiation-
96606f32e7eSjoerg   /// dependent, then we can entirely avoid its capture.
96706f32e7eSjoerg   ///
96806f32e7eSjoerg   ///   const int n = 0;
96906f32e7eSjoerg   ///   [&] (auto x) {
97006f32e7eSjoerg   ///     (void)+n + x;
97106f32e7eSjoerg   ///   };
97206f32e7eSjoerg   /// Interestingly, this strategy would involve a capture of n, even though
97306f32e7eSjoerg   /// it's obviously not odr-used here, because the full-expression is
97406f32e7eSjoerg   /// instantiation-dependent.  It could be useful to avoid capturing such
97506f32e7eSjoerg   /// variables, even when they are referred to in an instantiation-dependent
97606f32e7eSjoerg   /// expression, if we can unambiguously determine that they shall never be
97706f32e7eSjoerg   /// odr-used.  This would involve removal of the variable-referring-expression
97806f32e7eSjoerg   /// from the array of PotentialCaptures during the lvalue-to-rvalue
97906f32e7eSjoerg   /// conversions.  But per the working draft N3797, (post-chicago 2013) we must
98006f32e7eSjoerg   /// capture such variables.
98106f32e7eSjoerg   /// Before anyone is tempted to implement a strategy for not-capturing 'n',
98206f32e7eSjoerg   /// consider the insightful warning in:
98306f32e7eSjoerg   ///    /cfe-commits/Week-of-Mon-20131104/092596.html
98406f32e7eSjoerg   /// "The problem is that the set of captures for a lambda is part of the ABI
98506f32e7eSjoerg   ///  (since lambda layout can be made visible through inline functions and the
98606f32e7eSjoerg   ///  like), and there are no guarantees as to which cases we'll manage to build
98706f32e7eSjoerg   ///  an lvalue-to-rvalue conversion in, when parsing a template -- some
98806f32e7eSjoerg   ///  seemingly harmless change elsewhere in Sema could cause us to start or stop
98906f32e7eSjoerg   ///  building such a node. So we need a rule that anyone can implement and get
99006f32e7eSjoerg   ///  exactly the same result".
markVariableExprAsNonODRUsed(Expr * CapturingVarExpr)99106f32e7eSjoerg   void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
99206f32e7eSjoerg     assert(isa<DeclRefExpr>(CapturingVarExpr) ||
99306f32e7eSjoerg            isa<MemberExpr>(CapturingVarExpr) ||
99406f32e7eSjoerg            isa<FunctionParmPackExpr>(CapturingVarExpr));
99506f32e7eSjoerg     NonODRUsedCapturingExprs.insert(CapturingVarExpr);
99606f32e7eSjoerg   }
isVariableExprMarkedAsNonODRUsed(Expr * CapturingVarExpr)99706f32e7eSjoerg   bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
99806f32e7eSjoerg     assert(isa<DeclRefExpr>(CapturingVarExpr) ||
99906f32e7eSjoerg            isa<MemberExpr>(CapturingVarExpr) ||
100006f32e7eSjoerg            isa<FunctionParmPackExpr>(CapturingVarExpr));
100106f32e7eSjoerg     return NonODRUsedCapturingExprs.count(CapturingVarExpr);
100206f32e7eSjoerg   }
removePotentialCapture(Expr * E)100306f32e7eSjoerg   void removePotentialCapture(Expr *E) {
100406f32e7eSjoerg     PotentiallyCapturingExprs.erase(
100506f32e7eSjoerg         std::remove(PotentiallyCapturingExprs.begin(),
100606f32e7eSjoerg             PotentiallyCapturingExprs.end(), E),
100706f32e7eSjoerg         PotentiallyCapturingExprs.end());
100806f32e7eSjoerg   }
clearPotentialCaptures()100906f32e7eSjoerg   void clearPotentialCaptures() {
101006f32e7eSjoerg     PotentiallyCapturingExprs.clear();
101106f32e7eSjoerg     PotentialThisCaptureLocation = SourceLocation();
101206f32e7eSjoerg   }
getNumPotentialVariableCaptures()101306f32e7eSjoerg   unsigned getNumPotentialVariableCaptures() const {
101406f32e7eSjoerg     return PotentiallyCapturingExprs.size();
101506f32e7eSjoerg   }
101606f32e7eSjoerg 
hasPotentialCaptures()101706f32e7eSjoerg   bool hasPotentialCaptures() const {
101806f32e7eSjoerg     return getNumPotentialVariableCaptures() ||
101906f32e7eSjoerg                                   PotentialThisCaptureLocation.isValid();
102006f32e7eSjoerg   }
102106f32e7eSjoerg 
102206f32e7eSjoerg   void visitPotentialCaptures(
102306f32e7eSjoerg       llvm::function_ref<void(VarDecl *, Expr *)> Callback) const;
102406f32e7eSjoerg };
102506f32e7eSjoerg 
WeakObjectProfileTy()102606f32e7eSjoerg FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
102706f32e7eSjoerg     : Base(nullptr, false) {}
102806f32e7eSjoerg 
102906f32e7eSjoerg FunctionScopeInfo::WeakObjectProfileTy
getSentinel()103006f32e7eSjoerg FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
103106f32e7eSjoerg   FunctionScopeInfo::WeakObjectProfileTy Result;
103206f32e7eSjoerg   Result.Base.setInt(true);
103306f32e7eSjoerg   return Result;
103406f32e7eSjoerg }
103506f32e7eSjoerg 
103606f32e7eSjoerg template <typename ExprT>
recordUseOfWeak(const ExprT * E,bool IsRead)103706f32e7eSjoerg void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
103806f32e7eSjoerg   assert(E);
103906f32e7eSjoerg   WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
104006f32e7eSjoerg   Uses.push_back(WeakUseTy(E, IsRead));
104106f32e7eSjoerg }
104206f32e7eSjoerg 
addThisCapture(bool isNested,SourceLocation Loc,QualType CaptureType,bool ByCopy)104306f32e7eSjoerg inline void CapturingScopeInfo::addThisCapture(bool isNested,
104406f32e7eSjoerg                                                SourceLocation Loc,
104506f32e7eSjoerg                                                QualType CaptureType,
104606f32e7eSjoerg                                                bool ByCopy) {
104706f32e7eSjoerg   Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
104806f32e7eSjoerg                              ByCopy, /*Invalid*/ false));
104906f32e7eSjoerg   CXXThisCaptureIndex = Captures.size();
105006f32e7eSjoerg }
105106f32e7eSjoerg 
105206f32e7eSjoerg } // namespace sema
105306f32e7eSjoerg 
105406f32e7eSjoerg } // namespace clang
105506f32e7eSjoerg 
105606f32e7eSjoerg #endif // LLVM_CLANG_SEMA_SCOPEINFO_H
1057