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