1 //===--- LambdaCapture.h - Types for C++ Lambda Captures --------*- 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 /// \file
11 /// \brief Defines the LambdaCapture class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_LAMBDACAPTURE_H
16 #define LLVM_CLANG_AST_LAMBDACAPTURE_H
17 
18 #include "clang/AST/Decl.h"
19 #include "clang/Basic/Lambda.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 
22 namespace clang {
23 
24 /// \brief Describes the capture of a variable or of \c this, or of a
25 /// C++1y init-capture.
26 class LambdaCapture {
27   enum {
28     /// \brief Flag used by the Capture class to indicate that the given
29     /// capture was implicit.
30     Capture_Implicit = 0x01,
31 
32     /// \brief Flag used by the Capture class to indicate that the
33     /// given capture was by-copy.
34     ///
35     /// This includes the case of a non-reference init-capture.
36     Capture_ByCopy = 0x02
37   };
38 
39   llvm::PointerIntPair<Decl *, 2> DeclAndBits;
40   SourceLocation Loc;
41   SourceLocation EllipsisLoc;
42 
43   friend class ASTStmtReader;
44   friend class ASTStmtWriter;
45 
46 public:
47   /// \brief Create a new capture of a variable or of \c this.
48   ///
49   /// \param Loc The source location associated with this capture.
50   ///
51   /// \param Kind The kind of capture (this, byref, bycopy), which must
52   /// not be init-capture.
53   ///
54   /// \param Implicit Whether the capture was implicit or explicit.
55   ///
56   /// \param Var The local variable being captured, or null if capturing
57   /// \c this.
58   ///
59   /// \param EllipsisLoc The location of the ellipsis (...) for a
60   /// capture that is a pack expansion, or an invalid source
61   /// location to indicate that this is not a pack expansion.
62   LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
63                 VarDecl *Var = nullptr,
64                 SourceLocation EllipsisLoc = SourceLocation());
65 
66   /// \brief Determine the kind of capture.
67   LambdaCaptureKind getCaptureKind() const;
68 
69   /// \brief Determine whether this capture handles the C++ \c this
70   /// pointer.
capturesThis()71   bool capturesThis() const {
72     return (DeclAndBits.getPointer() == nullptr) &&
73            !(DeclAndBits.getInt() & Capture_ByCopy);
74   }
75 
76   /// \brief Determine whether this capture handles a variable.
capturesVariable()77   bool capturesVariable() const {
78     return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
79   }
80 
81   /// \brief Determine whether this captures a variable length array bound
82   /// expression.
capturesVLAType()83   bool capturesVLAType() const {
84     return (DeclAndBits.getPointer() == nullptr) &&
85            (DeclAndBits.getInt() & Capture_ByCopy);
86   }
87 
88   /// \brief Determine whether this is an init-capture.
isInitCapture()89   bool isInitCapture() const {
90     return capturesVariable() && getCapturedVar()->isInitCapture();
91   }
92 
93   /// \brief Retrieve the declaration of the local variable being
94   /// captured.
95   ///
96   /// This operation is only valid if this capture is a variable capture
97   /// (other than a capture of \c this).
getCapturedVar()98   VarDecl *getCapturedVar() const {
99     assert(capturesVariable() && "No variable available for 'this' capture");
100     return cast<VarDecl>(DeclAndBits.getPointer());
101   }
102 
103   /// \brief Determine whether this was an implicit capture (not
104   /// written between the square brackets introducing the lambda).
isImplicit()105   bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; }
106 
107   /// \brief Determine whether this was an explicit capture (written
108   /// between the square brackets introducing the lambda).
isExplicit()109   bool isExplicit() const { return !isImplicit(); }
110 
111   /// \brief Retrieve the source location of the capture.
112   ///
113   /// For an explicit capture, this returns the location of the
114   /// explicit capture in the source. For an implicit capture, this
115   /// returns the location at which the variable or \c this was first
116   /// used.
getLocation()117   SourceLocation getLocation() const { return Loc; }
118 
119   /// \brief Determine whether this capture is a pack expansion,
120   /// which captures a function parameter pack.
isPackExpansion()121   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
122 
123   /// \brief Retrieve the location of the ellipsis for a capture
124   /// that is a pack expansion.
getEllipsisLoc()125   SourceLocation getEllipsisLoc() const {
126     assert(isPackExpansion() && "No ellipsis location for a non-expansion");
127     return EllipsisLoc;
128   }
129 };
130 
131 } // end namespace clang
132 
133 #endif // LLVM_CLANG_AST_LAMBDACAPTURE_H
134