//===- ExprCXX.h - Classes for representing expressions ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the clang::Expr interface and subclasses for C++ expressions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H

#include "clang/AST/ASTConcept.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/ExpressionTraits.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>

namespace clang {

class ASTContext;
class DeclAccessPair;
class IdentifierInfo;
class LambdaCapture;
class NonTypeTemplateParmDecl;
class TemplateParameterList;

//===--------------------------------------------------------------------===//
// C++ Expressions.
//===--------------------------------------------------------------------===//

/// A call to an overloaded operator written using operator
/// syntax.
///
/// Represents a call to an overloaded operator written using operator
/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a
/// normal call, this AST node provides better information about the
/// syntactic representation of the call.
///
/// In a C++ template, this expression node kind will be used whenever
/// any of the arguments are type-dependent. In this case, the
/// function itself will be a (possibly empty) set of functions and
/// function templates that were found by name lookup at template
/// definition time.
class CXXOperatorCallExpr final : public CallExpr {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  SourceRange Range;
  FPOptionsOverride Overrides;

  // CXXOperatorCallExpr has some trailing objects belonging
  // to CallExpr. See CallExpr for the details.

  SourceRange getSourceRangeImpl() const LLVM_READONLY;

  CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn,
                      ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
                      SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
                      ADLCallKind UsesADL);

  CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);

public:
  static CXXOperatorCallExpr *
  Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
         ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
         SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
         ADLCallKind UsesADL = NotADL);

  static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
                                          unsigned NumArgs, EmptyShell Empty);

  /// Returns the kind of overloaded operator that this expression refers to.
  OverloadedOperatorKind getOperator() const {
    return static_cast<OverloadedOperatorKind>(
        CXXOperatorCallExprBits.OperatorKind);
  }

  static bool isAssignmentOp(OverloadedOperatorKind Opc) {
    return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual ||
           Opc == OO_PercentEqual || Opc == OO_PlusEqual ||
           Opc == OO_MinusEqual || Opc == OO_LessLessEqual ||
           Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual ||
           Opc == OO_CaretEqual || Opc == OO_PipeEqual;
  }
  bool isAssignmentOp() const { return isAssignmentOp(getOperator()); }

  static bool isComparisonOp(OverloadedOperatorKind Opc) {
    switch (Opc) {
    case OO_EqualEqual:
    case OO_ExclaimEqual:
    case OO_Greater:
    case OO_GreaterEqual:
    case OO_Less:
    case OO_LessEqual:
    case OO_Spaceship:
      return true;
    default:
      return false;
    }
  }
  bool isComparisonOp() const { return isComparisonOp(getOperator()); }

  /// Is this written as an infix binary operator?
  bool isInfixBinaryOp() const;

  /// Returns the location of the operator symbol in the expression.
  ///
  /// When \c getOperator()==OO_Call, this is the location of the right
  /// parentheses; when \c getOperator()==OO_Subscript, this is the location
  /// of the right bracket.
  SourceLocation getOperatorLoc() const { return getRParenLoc(); }

  SourceLocation getExprLoc() const LLVM_READONLY {
    OverloadedOperatorKind Operator = getOperator();
    return (Operator < OO_Plus || Operator >= OO_Arrow ||
            Operator == OO_PlusPlus || Operator == OO_MinusMinus)
               ? getBeginLoc()
               : getOperatorLoc();
  }

  SourceLocation getBeginLoc() const { return Range.getBegin(); }
  SourceLocation getEndLoc() const { return Range.getEnd(); }
  SourceRange getSourceRange() const { return Range; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXOperatorCallExprClass;
  }

  // Set the FPFeatures status of this operator. Only meaningful for
  // operations on floating point types.
  void setFPFeatures(FPOptionsOverride F) { Overrides = F; }
  FPOptionsOverride getFPFeatures() const { return Overrides; }
};

/// Represents a call to a member function that
/// may be written either with member call syntax (e.g., "obj.func()"
/// or "objptr->func()") or with normal function-call syntax
/// ("func()") within a member function that ends up calling a member
/// function. The callee in either case is a MemberExpr that contains
/// both the object argument and the member function, while the
/// arguments are the arguments within the parentheses (not including
/// the object argument).
class CXXMemberCallExpr final : public CallExpr {
  // CXXMemberCallExpr has some trailing objects belonging
  // to CallExpr. See CallExpr for the details.

  CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
                    ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs);

  CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty);

public:
  static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
                                   ArrayRef<Expr *> Args, QualType Ty,
                                   ExprValueKind VK, SourceLocation RP,
                                   unsigned MinNumArgs = 0);

  static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
                                        EmptyShell Empty);

  /// Retrieve the implicit object argument for the member call.
  ///
  /// For example, in "x.f(5)", this returns the sub-expression "x".
  Expr *getImplicitObjectArgument() const;

  /// Retrieve the type of the object argument.
  ///
  /// Note that this always returns a non-pointer type.
  QualType getObjectType() const;

  /// Retrieve the declaration of the called method.
  CXXMethodDecl *getMethodDecl() const;

  /// Retrieve the CXXRecordDecl for the underlying type of
  /// the implicit object argument.
  ///
  /// Note that this is may not be the same declaration as that of the class
  /// context of the CXXMethodDecl which this function is calling.
  /// FIXME: Returns 0 for member pointer call exprs.
  CXXRecordDecl *getRecordDecl() const;

  SourceLocation getExprLoc() const LLVM_READONLY {
    SourceLocation CLoc = getCallee()->getExprLoc();
    if (CLoc.isValid())
      return CLoc;

    return getBeginLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXMemberCallExprClass;
  }
};

/// Represents a call to a CUDA kernel function.
class CUDAKernelCallExpr final : public CallExpr {
  friend class ASTStmtReader;

  enum { CONFIG, END_PREARG };

  // CUDAKernelCallExpr has some trailing objects belonging
  // to CallExpr. See CallExpr for the details.

  CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args,
                     QualType Ty, ExprValueKind VK, SourceLocation RP,
                     unsigned MinNumArgs);

  CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty);

public:
  static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
                                    CallExpr *Config, ArrayRef<Expr *> Args,
                                    QualType Ty, ExprValueKind VK,
                                    SourceLocation RP, unsigned MinNumArgs = 0);

  static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx,
                                         unsigned NumArgs, EmptyShell Empty);

  const CallExpr *getConfig() const {
    return cast_or_null<CallExpr>(getPreArg(CONFIG));
  }
  CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CUDAKernelCallExprClass;
  }
};

/// A rewritten comparison expression that was originally written using
/// operator syntax.
///
/// In C++20, the following rewrites are performed:
/// - <tt>a == b</tt> -> <tt>b == a</tt>
/// - <tt>a != b</tt> -> <tt>!(a == b)</tt>
/// - <tt>a != b</tt> -> <tt>!(b == a)</tt>
/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>:
///   - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt>
///   - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt>
///
/// This expression provides access to both the original syntax and the
/// rewritten expression.
///
/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically
/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators.
class CXXRewrittenBinaryOperator : public Expr {
  friend class ASTStmtReader;

  /// The rewritten semantic form.
  Stmt *SemanticForm;

public:
  CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed)
      : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(),
             SemanticForm->getValueKind(), SemanticForm->getObjectKind()),
        SemanticForm(SemanticForm) {
    CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed;
    setDependence(computeDependence(this));
  }
  CXXRewrittenBinaryOperator(EmptyShell Empty)
      : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {}

  /// Get an equivalent semantic form for this expression.
  Expr *getSemanticForm() { return cast<Expr>(SemanticForm); }
  const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); }

  struct DecomposedForm {
    /// The original opcode, prior to rewriting.
    BinaryOperatorKind Opcode;
    /// The original left-hand side.
    const Expr *LHS;
    /// The original right-hand side.
    const Expr *RHS;
    /// The inner \c == or \c <=> operator expression.
    const Expr *InnerBinOp;
  };

  /// Decompose this operator into its syntactic form.
  DecomposedForm getDecomposedForm() const LLVM_READONLY;

  /// Determine whether this expression was rewritten in reverse form.
  bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; }

  BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; }
  const Expr *getLHS() const { return getDecomposedForm().LHS; }
  const Expr *getRHS() const { return getDecomposedForm().RHS; }

  SourceLocation getOperatorLoc() const LLVM_READONLY {
    return getDecomposedForm().InnerBinOp->getExprLoc();
  }
  SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); }

  /// Compute the begin and end locations from the decomposed form.
  /// The locations of the semantic form are not reliable if this is
  /// a reversed expression.
  //@{
  SourceLocation getBeginLoc() const LLVM_READONLY {
    return getDecomposedForm().LHS->getBeginLoc();
  }
  SourceLocation getEndLoc() const LLVM_READONLY {
    return getDecomposedForm().RHS->getEndLoc();
  }
  SourceRange getSourceRange() const LLVM_READONLY {
    DecomposedForm DF = getDecomposedForm();
    return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc());
  }
  //@}

  child_range children() {
    return child_range(&SemanticForm, &SemanticForm + 1);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXRewrittenBinaryOperatorClass;
  }
};

/// Abstract class common to all of the C++ "named"/"keyword" casts.
///
/// This abstract class is inherited by all of the classes
/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
/// reinterpret_cast, CXXConstCastExpr for \c const_cast and
/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL).
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
  // the location of the casting op
  SourceLocation Loc;

  // the location of the right parenthesis
  SourceLocation RParenLoc;

  // range for '<' '>'
  SourceRange AngleBrackets;

protected:
  friend class ASTStmtReader;

  CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
                   CastKind kind, Expr *op, unsigned PathSize,
                   TypeSourceInfo *writtenTy, SourceLocation l,
                   SourceLocation RParenLoc,
                   SourceRange AngleBrackets)
      : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
        RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}

  explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
      : ExplicitCastExpr(SC, Shell, PathSize) {}

public:
  const char *getCastName() const;

  /// Retrieve the location of the cast operator keyword, e.g.,
  /// \c static_cast.
  SourceLocation getOperatorLoc() const { return Loc; }

  /// Retrieve the location of the closing parenthesis.
  SourceLocation getRParenLoc() const { return RParenLoc; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
  SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; }

  static bool classof(const Stmt *T) {
    switch (T->getStmtClass()) {
    case CXXStaticCastExprClass:
    case CXXDynamicCastExprClass:
    case CXXReinterpretCastExprClass:
    case CXXConstCastExprClass:
    case CXXAddrspaceCastExprClass:
      return true;
    default:
      return false;
    }
  }
};

/// A C++ \c static_cast expression (C++ [expr.static.cast]).
///
/// This expression node represents a C++ static cast, e.g.,
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
  CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
                    unsigned pathSize, TypeSourceInfo *writtenTy,
                    SourceLocation l, SourceLocation RParenLoc,
                    SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
                         writtenTy, l, RParenLoc, AngleBrackets) {}

  explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
      : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T,
                                   ExprValueKind VK, CastKind K, Expr *Op,
                                   const CXXCastPath *Path,
                                   TypeSourceInfo *Written, SourceLocation L,
                                   SourceLocation RParenLoc,
                                   SourceRange AngleBrackets);
  static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context,
                                        unsigned PathSize);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXStaticCastExprClass;
  }
};

/// A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
///
/// This expression node represents a dynamic cast, e.g.,
/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
/// check to determine how to perform the type conversion.
class CXXDynamicCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
  CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
                     Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
                     SourceLocation l, SourceLocation RParenLoc,
                     SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
                         writtenTy, l, RParenLoc, AngleBrackets) {}

  explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
      : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T,
                                    ExprValueKind VK, CastKind Kind, Expr *Op,
                                    const CXXCastPath *Path,
                                    TypeSourceInfo *Written, SourceLocation L,
                                    SourceLocation RParenLoc,
                                    SourceRange AngleBrackets);

  static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context,
                                         unsigned pathSize);

  bool isAlwaysNull() const;

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXDynamicCastExprClass;
  }
};

/// A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
///
/// A reinterpret_cast provides a differently-typed view of a value but
/// (in Clang, as in most C++ implementations) performs no actual work at
/// run time.
class CXXReinterpretCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXReinterpretCastExpr,
                                    CXXBaseSpecifier *> {
  CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
                         Expr *op, unsigned pathSize,
                         TypeSourceInfo *writtenTy, SourceLocation l,
                         SourceLocation RParenLoc,
                         SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
                         pathSize, writtenTy, l, RParenLoc, AngleBrackets) {}

  CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
      : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T,
                                        ExprValueKind VK, CastKind Kind,
                                        Expr *Op, const CXXCastPath *Path,
                                 TypeSourceInfo *WrittenTy, SourceLocation L,
                                        SourceLocation RParenLoc,
                                        SourceRange AngleBrackets);
  static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context,
                                             unsigned pathSize);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXReinterpretCastExprClass;
  }
};

/// A C++ \c const_cast expression (C++ [expr.const.cast]).
///
/// This expression node represents a const cast, e.g.,
/// \c const_cast<char*>(PtrToConstChar).
///
/// A const_cast can remove type qualifiers but does not change the underlying
/// value.
class CXXConstCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
  CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
                   TypeSourceInfo *writtenTy, SourceLocation l,
                   SourceLocation RParenLoc, SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
                         0, writtenTy, l, RParenLoc, AngleBrackets) {}

  explicit CXXConstCastExpr(EmptyShell Empty)
      : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXConstCastExpr *Create(const ASTContext &Context, QualType T,
                                  ExprValueKind VK, Expr *Op,
                                  TypeSourceInfo *WrittenTy, SourceLocation L,
                                  SourceLocation RParenLoc,
                                  SourceRange AngleBrackets);
  static CXXConstCastExpr *CreateEmpty(const ASTContext &Context);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXConstCastExprClass;
  }
};

/// A C++ addrspace_cast expression (currently only enabled for OpenCL).
///
/// This expression node represents a cast between pointers to objects in
/// different address spaces e.g.,
/// \c addrspace_cast<global int*>(PtrToGenericInt).
///
/// A addrspace_cast can cast address space type qualifiers but does not change
/// the underlying value.
class CXXAddrspaceCastExpr final
    : public CXXNamedCastExpr,
      private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> {
  CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op,
                       TypeSourceInfo *writtenTy, SourceLocation l,
                       SourceLocation RParenLoc, SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0,
                         writtenTy, l, RParenLoc, AngleBrackets) {}

  explicit CXXAddrspaceCastExpr(EmptyShell Empty)
      : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXAddrspaceCastExpr *
  Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind,
         Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L,
         SourceLocation RParenLoc, SourceRange AngleBrackets);
  static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXAddrspaceCastExprClass;
  }
};

/// A call to a literal operator (C++11 [over.literal])
/// written as a user-defined literal (C++11 [lit.ext]).
///
/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
/// is semantically equivalent to a normal call, this AST node provides better
/// information about the syntactic representation of the literal.
///
/// Since literal operators are never found by ADL and can only be declared at
/// namespace scope, a user-defined literal is never dependent.
class UserDefinedLiteral final : public CallExpr {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  /// The location of a ud-suffix within the literal.
  SourceLocation UDSuffixLoc;

  // UserDefinedLiteral has some trailing objects belonging
  // to CallExpr. See CallExpr for the details.

  UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
                     ExprValueKind VK, SourceLocation LitEndLoc,
                     SourceLocation SuffixLoc);

  UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty);

public:
  static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn,
                                    ArrayRef<Expr *> Args, QualType Ty,
                                    ExprValueKind VK, SourceLocation LitEndLoc,
                                    SourceLocation SuffixLoc);

  static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx,
                                         unsigned NumArgs, EmptyShell Empty);

  /// The kind of literal operator which is invoked.
  enum LiteralOperatorKind {
    /// Raw form: operator "" X (const char *)
    LOK_Raw,

    /// Raw form: operator "" X<cs...> ()
    LOK_Template,

    /// operator "" X (unsigned long long)
    LOK_Integer,

    /// operator "" X (long double)
    LOK_Floating,

    /// operator "" X (const CharT *, size_t)
    LOK_String,

    /// operator "" X (CharT)
    LOK_Character
  };

  /// Returns the kind of literal operator invocation
  /// which this expression represents.
  LiteralOperatorKind getLiteralOperatorKind() const;

  /// If this is not a raw user-defined literal, get the
  /// underlying cooked literal (representing the literal with the suffix
  /// removed).
  Expr *getCookedLiteral();
  const Expr *getCookedLiteral() const {
    return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral();
  }

  SourceLocation getBeginLoc() const {
    if (getLiteralOperatorKind() == LOK_Template)
      return getRParenLoc();
    return getArg(0)->getBeginLoc();
  }

  SourceLocation getEndLoc() const { return getRParenLoc(); }

  /// Returns the location of a ud-suffix in the expression.
  ///
  /// For a string literal, there may be multiple identical suffixes. This
  /// returns the first.
  SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; }

  /// Returns the ud-suffix specified for this literal.
  const IdentifierInfo *getUDSuffix() const;

  static bool classof(const Stmt *S) {
    return S->getStmtClass() == UserDefinedLiteralClass;
  }
};

/// A boolean literal, per ([C++ lex.bool] Boolean literals).
class CXXBoolLiteralExpr : public Expr {
public:
  CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc)
      : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary) {
    CXXBoolLiteralExprBits.Value = Val;
    CXXBoolLiteralExprBits.Loc = Loc;
    setDependence(ExprDependence::None);
  }

  explicit CXXBoolLiteralExpr(EmptyShell Empty)
      : Expr(CXXBoolLiteralExprClass, Empty) {}

  bool getValue() const { return CXXBoolLiteralExprBits.Value; }
  void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; }

  SourceLocation getBeginLoc() const { return getLocation(); }
  SourceLocation getEndLoc() const { return getLocation(); }

  SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; }
  void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXBoolLiteralExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// The null pointer literal (C++11 [lex.nullptr])
///
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
class CXXNullPtrLiteralExpr : public Expr {
public:
  CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc)
      : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary) {
    CXXNullPtrLiteralExprBits.Loc = Loc;
    setDependence(ExprDependence::None);
  }

  explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
      : Expr(CXXNullPtrLiteralExprClass, Empty) {}

  SourceLocation getBeginLoc() const { return getLocation(); }
  SourceLocation getEndLoc() const { return getLocation(); }

  SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; }
  void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXNullPtrLiteralExprClass;
  }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Implicit construction of a std::initializer_list<T> object from an
/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
class CXXStdInitializerListExpr : public Expr {
  Stmt *SubExpr = nullptr;

  CXXStdInitializerListExpr(EmptyShell Empty)
      : Expr(CXXStdInitializerListExprClass, Empty) {}

public:
  friend class ASTReader;
  friend class ASTStmtReader;

  CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
      : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary),
        SubExpr(SubExpr) {
    setDependence(computeDependence(this));
  }

  Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
  const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return SubExpr->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return SubExpr->getEndLoc();
  }

  /// Retrieve the source range of the expression.
  SourceRange getSourceRange() const LLVM_READONLY {
    return SubExpr->getSourceRange();
  }

  static bool classof(const Stmt *S) {
    return S->getStmtClass() == CXXStdInitializerListExprClass;
  }

  child_range children() { return child_range(&SubExpr, &SubExpr + 1); }

  const_child_range children() const {
    return const_child_range(&SubExpr, &SubExpr + 1);
  }
};

/// A C++ \c typeid expression (C++ [expr.typeid]), which gets
/// the \c type_info that corresponds to the supplied type, or the (possibly
/// dynamic) type of the supplied expression.
///
/// This represents code like \c typeid(int) or \c typeid(*objPtr)
class CXXTypeidExpr : public Expr {
  friend class ASTStmtReader;

private:
  llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
  SourceRange Range;

public:
  CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
      : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
        Range(R) {
    setDependence(computeDependence(this));
  }

  CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
      : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
        Range(R) {
    setDependence(computeDependence(this));
  }

  CXXTypeidExpr(EmptyShell Empty, bool isExpr)
      : Expr(CXXTypeidExprClass, Empty) {
    if (isExpr)
      Operand = (Expr*)nullptr;
    else
      Operand = (TypeSourceInfo*)nullptr;
  }

  /// Determine whether this typeid has a type operand which is potentially
  /// evaluated, per C++11 [expr.typeid]p3.
  bool isPotentiallyEvaluated() const;

  bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }

  /// Retrieves the type operand of this typeid() expression after
  /// various required adjustments (removing reference types, cv-qualifiers).
  QualType getTypeOperand(ASTContext &Context) const;

  /// Retrieve source information for the type operand.
  TypeSourceInfo *getTypeOperandSourceInfo() const {
    assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
    return Operand.get<TypeSourceInfo *>();
  }
  Expr *getExprOperand() const {
    assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
    return static_cast<Expr*>(Operand.get<Stmt *>());
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
  void setSourceRange(SourceRange R) { Range = R; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXTypeidExprClass;
  }

  // Iterators
  child_range children() {
    if (isTypeOperand())
      return child_range(child_iterator(), child_iterator());
    auto **begin = reinterpret_cast<Stmt **>(&Operand);
    return child_range(begin, begin + 1);
  }

  const_child_range children() const {
    if (isTypeOperand())
      return const_child_range(const_child_iterator(), const_child_iterator());

    auto **begin =
        reinterpret_cast<Stmt **>(&const_cast<CXXTypeidExpr *>(this)->Operand);
    return const_child_range(begin, begin + 1);
  }
};

/// A member reference to an MSPropertyDecl.
///
/// This expression always has pseudo-object type, and therefore it is
/// typically not encountered in a fully-typechecked expression except
/// within the syntactic form of a PseudoObjectExpr.
class MSPropertyRefExpr : public Expr {
  Expr *BaseExpr;
  MSPropertyDecl *TheDecl;
  SourceLocation MemberLoc;
  bool IsArrow;
  NestedNameSpecifierLoc QualifierLoc;

public:
  friend class ASTStmtReader;

  MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
                    QualType ty, ExprValueKind VK,
                    NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc)
      : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary), BaseExpr(baseExpr),
        TheDecl(decl), MemberLoc(nameLoc), IsArrow(isArrow),
        QualifierLoc(qualifierLoc) {
    setDependence(computeDependence(this));
  }

  MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}

  SourceRange getSourceRange() const LLVM_READONLY {
    return SourceRange(getBeginLoc(), getEndLoc());
  }

  bool isImplicitAccess() const {
    return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
  }

  SourceLocation getBeginLoc() const {
    if (!isImplicitAccess())
      return BaseExpr->getBeginLoc();
    else if (QualifierLoc)
      return QualifierLoc.getBeginLoc();
    else
        return MemberLoc;
  }

  SourceLocation getEndLoc() const { return getMemberLoc(); }

  child_range children() {
    return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
  }

  const_child_range children() const {
    auto Children = const_cast<MSPropertyRefExpr *>(this)->children();
    return const_child_range(Children.begin(), Children.end());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == MSPropertyRefExprClass;
  }

  Expr *getBaseExpr() const { return BaseExpr; }
  MSPropertyDecl *getPropertyDecl() const { return TheDecl; }
  bool isArrow() const { return IsArrow; }
  SourceLocation getMemberLoc() const { return MemberLoc; }
  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
};

/// MS property subscript expression.
/// MSVC supports 'property' attribute and allows to apply it to the
/// declaration of an empty array in a class or structure definition.
/// For example:
/// \code
/// __declspec(property(get=GetX, put=PutX)) int x[];
/// \endcode
/// The above statement indicates that x[] can be used with one or more array
/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and
/// p->x[a][b] = i will be turned into p->PutX(a, b, i).
/// This is a syntactic pseudo-object expression.
class MSPropertySubscriptExpr : public Expr {
  friend class ASTStmtReader;

  enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 };

  Stmt *SubExprs[NUM_SUBEXPRS];
  SourceLocation RBracketLoc;

  void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; }
  void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; }

public:
  MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK,
                          ExprObjectKind OK, SourceLocation RBracketLoc)
      : Expr(MSPropertySubscriptExprClass, Ty, VK, OK),
        RBracketLoc(RBracketLoc) {
    SubExprs[BASE_EXPR] = Base;
    SubExprs[IDX_EXPR] = Idx;
    setDependence(computeDependence(this));
  }

  /// Create an empty array subscript expression.
  explicit MSPropertySubscriptExpr(EmptyShell Shell)
      : Expr(MSPropertySubscriptExprClass, Shell) {}

  Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); }
  const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); }

  Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); }
  const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return getBase()->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }

  SourceLocation getRBracketLoc() const { return RBracketLoc; }
  void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }

  SourceLocation getExprLoc() const LLVM_READONLY {
    return getBase()->getExprLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == MSPropertySubscriptExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
  }

  const_child_range children() const {
    return const_child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
  }
};

/// A Microsoft C++ @c __uuidof expression, which gets
/// the _GUID that corresponds to the supplied type or expression.
///
/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
class CXXUuidofExpr : public Expr {
  friend class ASTStmtReader;

private:
  llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
  MSGuidDecl *Guid;
  SourceRange Range;

public:
  CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, MSGuidDecl *Guid,
                SourceRange R)
      : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
        Guid(Guid), Range(R) {
    setDependence(computeDependence(this));
  }

  CXXUuidofExpr(QualType Ty, Expr *Operand, MSGuidDecl *Guid, SourceRange R)
      : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
        Guid(Guid), Range(R) {
    setDependence(computeDependence(this));
  }

  CXXUuidofExpr(EmptyShell Empty, bool isExpr)
    : Expr(CXXUuidofExprClass, Empty) {
    if (isExpr)
      Operand = (Expr*)nullptr;
    else
      Operand = (TypeSourceInfo*)nullptr;
  }

  bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }

  /// Retrieves the type operand of this __uuidof() expression after
  /// various required adjustments (removing reference types, cv-qualifiers).
  QualType getTypeOperand(ASTContext &Context) const;

  /// Retrieve source information for the type operand.
  TypeSourceInfo *getTypeOperandSourceInfo() const {
    assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
    return Operand.get<TypeSourceInfo *>();
  }
  Expr *getExprOperand() const {
    assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
    return static_cast<Expr*>(Operand.get<Stmt *>());
  }

  MSGuidDecl *getGuidDecl() const { return Guid; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
  void setSourceRange(SourceRange R) { Range = R; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXUuidofExprClass;
  }

  // Iterators
  child_range children() {
    if (isTypeOperand())
      return child_range(child_iterator(), child_iterator());
    auto **begin = reinterpret_cast<Stmt **>(&Operand);
    return child_range(begin, begin + 1);
  }

  const_child_range children() const {
    if (isTypeOperand())
      return const_child_range(const_child_iterator(), const_child_iterator());
    auto **begin =
        reinterpret_cast<Stmt **>(&const_cast<CXXUuidofExpr *>(this)->Operand);
    return const_child_range(begin, begin + 1);
  }
};

/// Represents the \c this expression in C++.
///
/// This is a pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
///
/// \code
/// class Foo {
/// public:
///   void bar();
///   void test() { this->bar(); }
/// };
/// \endcode
class CXXThisExpr : public Expr {
public:
  CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit)
      : Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary) {
    CXXThisExprBits.IsImplicit = IsImplicit;
    CXXThisExprBits.Loc = L;
    setDependence(computeDependence(this));
  }

  CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}

  SourceLocation getLocation() const { return CXXThisExprBits.Loc; }
  void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; }

  SourceLocation getBeginLoc() const { return getLocation(); }
  SourceLocation getEndLoc() const { return getLocation(); }

  bool isImplicit() const { return CXXThisExprBits.IsImplicit; }
  void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXThisExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// A C++ throw-expression (C++ [except.throw]).
///
/// This handles 'throw' (for re-throwing the current exception) and
/// 'throw' assignment-expression.  When assignment-expression isn't
/// present, Op will be null.
class CXXThrowExpr : public Expr {
  friend class ASTStmtReader;

  /// The optional expression in the throw statement.
  Stmt *Operand;

public:
  // \p Ty is the void type which is used as the result type of the
  // expression. The \p Loc is the location of the throw keyword.
  // \p Operand is the expression in the throw statement, and can be
  // null if not present.
  CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc,
               bool IsThrownVariableInScope)
      : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary), Operand(Operand) {
    CXXThrowExprBits.ThrowLoc = Loc;
    CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope;
    setDependence(computeDependence(this));
  }
  CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}

  const Expr *getSubExpr() const { return cast_or_null<Expr>(Operand); }
  Expr *getSubExpr() { return cast_or_null<Expr>(Operand); }

  SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; }

  /// Determines whether the variable thrown by this expression (if any!)
  /// is within the innermost try block.
  ///
  /// This information is required to determine whether the NRVO can apply to
  /// this variable.
  bool isThrownVariableInScope() const {
    return CXXThrowExprBits.IsThrownVariableInScope;
  }

  SourceLocation getBeginLoc() const { return getThrowLoc(); }
  SourceLocation getEndLoc() const LLVM_READONLY {
    if (!getSubExpr())
      return getThrowLoc();
    return getSubExpr()->getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXThrowExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(&Operand, Operand ? &Operand + 1 : &Operand);
  }

  const_child_range children() const {
    return const_child_range(&Operand, Operand ? &Operand + 1 : &Operand);
  }
};

/// A default argument (C++ [dcl.fct.default]).
///
/// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final : public Expr {
  friend class ASTStmtReader;

  /// The parameter whose default is being used.
  ParmVarDecl *Param;

  /// The context where the default argument expression was used.
  DeclContext *UsedContext;

  CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
                    DeclContext *UsedContext)
      : Expr(SC,
             Param->hasUnparsedDefaultArg()
                 ? Param->getType().getNonReferenceType()
                 : Param->getDefaultArg()->getType(),
             Param->getDefaultArg()->getValueKind(),
             Param->getDefaultArg()->getObjectKind()),
        Param(Param), UsedContext(UsedContext) {
    CXXDefaultArgExprBits.Loc = Loc;
    setDependence(ExprDependence::None);
  }

public:
  CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}

  // \p Param is the parameter whose default argument is used by this
  // expression.
  static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
                                   ParmVarDecl *Param,
                                   DeclContext *UsedContext) {
    return new (C)
        CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext);
  }

  // Retrieve the parameter that the argument was created from.
  const ParmVarDecl *getParam() const { return Param; }
  ParmVarDecl *getParam() { return Param; }

  // Retrieve the actual argument to the function call.
  const Expr *getExpr() const { return getParam()->getDefaultArg(); }
  Expr *getExpr() { return getParam()->getDefaultArg(); }

  const DeclContext *getUsedContext() const { return UsedContext; }
  DeclContext *getUsedContext() { return UsedContext; }

  /// Retrieve the location where this default argument was actually used.
  SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; }

  /// Default argument expressions have no representation in the
  /// source, so they have an empty source range.
  SourceLocation getBeginLoc() const { return SourceLocation(); }
  SourceLocation getEndLoc() const { return SourceLocation(); }

  SourceLocation getExprLoc() const { return getUsedLocation(); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXDefaultArgExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// A use of a default initializer in a constructor or in aggregate
/// initialization.
///
/// This wraps a use of a C++ default initializer (technically,
/// a brace-or-equal-initializer for a non-static data member) when it
/// is implicitly used in a mem-initializer-list in a constructor
/// (C++11 [class.base.init]p8) or in aggregate initialization
/// (C++1y [dcl.init.aggr]p7).
class CXXDefaultInitExpr : public Expr {
  friend class ASTReader;
  friend class ASTStmtReader;

  /// The field whose default is being used.
  FieldDecl *Field;

  /// The context where the default initializer expression was used.
  DeclContext *UsedContext;

  CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
                     FieldDecl *Field, QualType Ty, DeclContext *UsedContext);

  CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}

public:
  /// \p Field is the non-static data member whose default initializer is used
  /// by this expression.
  static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
                                    FieldDecl *Field, DeclContext *UsedContext) {
    return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext);
  }

  /// Get the field whose initializer will be used.
  FieldDecl *getField() { return Field; }
  const FieldDecl *getField() const { return Field; }

  /// Get the initialization expression that will be used.
  const Expr *getExpr() const {
    assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
    return Field->getInClassInitializer();
  }
  Expr *getExpr() {
    assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
    return Field->getInClassInitializer();
  }

  const DeclContext *getUsedContext() const { return UsedContext; }
  DeclContext *getUsedContext() { return UsedContext; }

  /// Retrieve the location where this default initializer expression was
  /// actually used.
  SourceLocation getUsedLocation() const { return getBeginLoc(); }

  SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; }
  SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXDefaultInitExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents a C++ temporary.
class CXXTemporary {
  /// The destructor that needs to be called.
  const CXXDestructorDecl *Destructor;

  explicit CXXTemporary(const CXXDestructorDecl *destructor)
      : Destructor(destructor) {}

public:
  static CXXTemporary *Create(const ASTContext &C,
                              const CXXDestructorDecl *Destructor);

  const CXXDestructorDecl *getDestructor() const { return Destructor; }

  void setDestructor(const CXXDestructorDecl *Dtor) {
    Destructor = Dtor;
  }
};

/// Represents binding an expression to a temporary.
///
/// This ensures the destructor is called for the temporary. It should only be
/// needed for non-POD, non-trivially destructable class types. For example:
///
/// \code
///   struct S {
///     S() { }  // User defined constructor makes S non-POD.
///     ~S() { } // User defined destructor makes it non-trivial.
///   };
///   void test() {
///     const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
///   }
/// \endcode
class CXXBindTemporaryExpr : public Expr {
  CXXTemporary *Temp = nullptr;
  Stmt *SubExpr = nullptr;

  CXXBindTemporaryExpr(CXXTemporary *temp, Expr *SubExpr)
      : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_RValue,
             OK_Ordinary),
        Temp(temp), SubExpr(SubExpr) {
    setDependence(computeDependence(this));
  }

public:
  CXXBindTemporaryExpr(EmptyShell Empty)
      : Expr(CXXBindTemporaryExprClass, Empty) {}

  static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp,
                                      Expr* SubExpr);

  CXXTemporary *getTemporary() { return Temp; }
  const CXXTemporary *getTemporary() const { return Temp; }
  void setTemporary(CXXTemporary *T) { Temp = T; }

  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
  void setSubExpr(Expr *E) { SubExpr = E; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return SubExpr->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return SubExpr->getEndLoc();
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXBindTemporaryExprClass;
  }

  // Iterators
  child_range children() { return child_range(&SubExpr, &SubExpr + 1); }

  const_child_range children() const {
    return const_child_range(&SubExpr, &SubExpr + 1);
  }
};

/// Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
  friend class ASTStmtReader;

public:
  enum ConstructionKind {
    CK_Complete,
    CK_NonVirtualBase,
    CK_VirtualBase,
    CK_Delegating
  };

private:
  /// A pointer to the constructor which will be ultimately called.
  CXXConstructorDecl *Constructor;

  SourceRange ParenOrBraceRange;

  /// The number of arguments.
  unsigned NumArgs;

  // We would like to stash the arguments of the constructor call after
  // CXXConstructExpr. However CXXConstructExpr is used as a base class of
  // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects
  // impossible.
  //
  // Instead we manually stash the trailing object after the full object
  // containing CXXConstructExpr (that is either CXXConstructExpr or
  // CXXTemporaryObjectExpr).
  //
  // The trailing objects are:
  //
  // * An array of getNumArgs() "Stmt *" for the arguments of the
  //   constructor call.

  /// Return a pointer to the start of the trailing arguments.
  /// Defined just after CXXTemporaryObjectExpr.
  inline Stmt **getTrailingArgs();
  const Stmt *const *getTrailingArgs() const {
    return const_cast<CXXConstructExpr *>(this)->getTrailingArgs();
  }

protected:
  /// Build a C++ construction expression.
  CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc,
                   CXXConstructorDecl *Ctor, bool Elidable,
                   ArrayRef<Expr *> Args, bool HadMultipleCandidates,
                   bool ListInitialization, bool StdInitListInitialization,
                   bool ZeroInitialization, ConstructionKind ConstructKind,
                   SourceRange ParenOrBraceRange);

  /// Build an empty C++ construction expression.
  CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs);

  /// Return the size in bytes of the trailing objects. Used by
  /// CXXTemporaryObjectExpr to allocate the right amount of storage.
  static unsigned sizeOfTrailingObjects(unsigned NumArgs) {
    return NumArgs * sizeof(Stmt *);
  }

public:
  /// Create a C++ construction expression.
  static CXXConstructExpr *
  Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc,
         CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args,
         bool HadMultipleCandidates, bool ListInitialization,
         bool StdInitListInitialization, bool ZeroInitialization,
         ConstructionKind ConstructKind, SourceRange ParenOrBraceRange);

  /// Create an empty C++ construction expression.
  static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs);

  /// Get the constructor that this expression will (ultimately) call.
  CXXConstructorDecl *getConstructor() const { return Constructor; }

  SourceLocation getLocation() const { return CXXConstructExprBits.Loc; }
  void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; }

  /// Whether this construction is elidable.
  bool isElidable() const { return CXXConstructExprBits.Elidable; }
  void setElidable(bool E) { CXXConstructExprBits.Elidable = E; }

  /// Whether the referred constructor was resolved from
  /// an overloaded set having size greater than 1.
  bool hadMultipleCandidates() const {
    return CXXConstructExprBits.HadMultipleCandidates;
  }
  void setHadMultipleCandidates(bool V) {
    CXXConstructExprBits.HadMultipleCandidates = V;
  }

  /// Whether this constructor call was written as list-initialization.
  bool isListInitialization() const {
    return CXXConstructExprBits.ListInitialization;
  }
  void setListInitialization(bool V) {
    CXXConstructExprBits.ListInitialization = V;
  }

  /// Whether this constructor call was written as list-initialization,
  /// but was interpreted as forming a std::initializer_list<T> from the list
  /// and passing that as a single constructor argument.
  /// See C++11 [over.match.list]p1 bullet 1.
  bool isStdInitListInitialization() const {
    return CXXConstructExprBits.StdInitListInitialization;
  }
  void setStdInitListInitialization(bool V) {
    CXXConstructExprBits.StdInitListInitialization = V;
  }

  /// Whether this construction first requires
  /// zero-initialization before the initializer is called.
  bool requiresZeroInitialization() const {
    return CXXConstructExprBits.ZeroInitialization;
  }
  void setRequiresZeroInitialization(bool ZeroInit) {
    CXXConstructExprBits.ZeroInitialization = ZeroInit;
  }

  /// Determine whether this constructor is actually constructing
  /// a base class (rather than a complete object).
  ConstructionKind getConstructionKind() const {
    return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind);
  }
  void setConstructionKind(ConstructionKind CK) {
    CXXConstructExprBits.ConstructionKind = CK;
  }

  using arg_iterator = ExprIterator;
  using const_arg_iterator = ConstExprIterator;
  using arg_range = llvm::iterator_range<arg_iterator>;
  using const_arg_range = llvm::iterator_range<const_arg_iterator>;

  arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
  const_arg_range arguments() const {
    return const_arg_range(arg_begin(), arg_end());
  }

  arg_iterator arg_begin() { return getTrailingArgs(); }
  arg_iterator arg_end() { return arg_begin() + getNumArgs(); }
  const_arg_iterator arg_begin() const { return getTrailingArgs(); }
  const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); }

  Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); }
  const Expr *const *getArgs() const {
    return reinterpret_cast<const Expr *const *>(getTrailingArgs());
  }

  /// Return the number of arguments to the constructor call.
  unsigned getNumArgs() const { return NumArgs; }

  /// Return the specified argument.
  Expr *getArg(unsigned Arg) {
    assert(Arg < getNumArgs() && "Arg access out of range!");
    return getArgs()[Arg];
  }
  const Expr *getArg(unsigned Arg) const {
    assert(Arg < getNumArgs() && "Arg access out of range!");
    return getArgs()[Arg];
  }

  /// Set the specified argument.
  void setArg(unsigned Arg, Expr *ArgExpr) {
    assert(Arg < getNumArgs() && "Arg access out of range!");
    getArgs()[Arg] = ArgExpr;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY;
  SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; }
  void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXConstructExprClass ||
           T->getStmtClass() == CXXTemporaryObjectExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs());
  }

  const_child_range children() const {
    auto Children = const_cast<CXXConstructExpr *>(this)->children();
    return const_child_range(Children.begin(), Children.end());
  }
};

/// Represents a call to an inherited base class constructor from an
/// inheriting constructor. This call implicitly forwards the arguments from
/// the enclosing context (an inheriting constructor) to the specified inherited
/// base class constructor.
class CXXInheritedCtorInitExpr : public Expr {
private:
  CXXConstructorDecl *Constructor = nullptr;

  /// The location of the using declaration.
  SourceLocation Loc;

  /// Whether this is the construction of a virtual base.
  unsigned ConstructsVirtualBase : 1;

  /// Whether the constructor is inherited from a virtual base class of the
  /// class that we construct.
  unsigned InheritedFromVirtualBase : 1;

public:
  friend class ASTStmtReader;

  /// Construct a C++ inheriting construction expression.
  CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T,
                           CXXConstructorDecl *Ctor, bool ConstructsVirtualBase,
                           bool InheritedFromVirtualBase)
      : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary),
        Constructor(Ctor), Loc(Loc),
        ConstructsVirtualBase(ConstructsVirtualBase),
        InheritedFromVirtualBase(InheritedFromVirtualBase) {
    assert(!T->isDependentType());
    setDependence(ExprDependence::None);
  }

  /// Construct an empty C++ inheriting construction expression.
  explicit CXXInheritedCtorInitExpr(EmptyShell Empty)
      : Expr(CXXInheritedCtorInitExprClass, Empty),
        ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {}

  /// Get the constructor that this expression will call.
  CXXConstructorDecl *getConstructor() const { return Constructor; }

  /// Determine whether this constructor is actually constructing
  /// a base class (rather than a complete object).
  bool constructsVBase() const { return ConstructsVirtualBase; }
  CXXConstructExpr::ConstructionKind getConstructionKind() const {
    return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase
                                 : CXXConstructExpr::CK_NonVirtualBase;
  }

  /// Determine whether the inherited constructor is inherited from a
  /// virtual base of the object we construct. If so, we are not responsible
  /// for calling the inherited constructor (the complete object constructor
  /// does that), and so we don't need to pass any arguments.
  bool inheritedFromVBase() const { return InheritedFromVirtualBase; }

  SourceLocation getLocation() const LLVM_READONLY { return Loc; }
  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXInheritedCtorInitExprClass;
  }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents an explicit C++ type conversion that uses "functional"
/// notation (C++ [expr.type.conv]).
///
/// Example:
/// \code
///   x = int(0.5);
/// \endcode
class CXXFunctionalCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
  SourceLocation LParenLoc;
  SourceLocation RParenLoc;

  CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
                        TypeSourceInfo *writtenTy,
                        CastKind kind, Expr *castExpr, unsigned pathSize,
                        SourceLocation lParenLoc, SourceLocation rParenLoc)
      : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
                         castExpr, pathSize, writtenTy),
        LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}

  explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
      : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}

public:
  friend class CastExpr;
  friend TrailingObjects;

  static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T,
                                       ExprValueKind VK,
                                       TypeSourceInfo *Written,
                                       CastKind Kind, Expr *Op,
                                       const CXXCastPath *Path,
                                       SourceLocation LPLoc,
                                       SourceLocation RPLoc);
  static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context,
                                            unsigned PathSize);

  SourceLocation getLParenLoc() const { return LParenLoc; }
  void setLParenLoc(SourceLocation L) { LParenLoc = L; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  /// Determine whether this expression models list-initialization.
  bool isListInitialization() const { return LParenLoc.isInvalid(); }

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY;

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXFunctionalCastExprClass;
  }
};

/// Represents a C++ functional cast expression that builds a
/// temporary object.
///
/// This expression type represents a C++ "functional" cast
/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
/// constructor to build a temporary object. With N == 1 arguments the
/// functional cast expression will be represented by CXXFunctionalCastExpr.
/// Example:
/// \code
/// struct X { X(int, float); }
///
/// X create_X() {
///   return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
/// };
/// \endcode
class CXXTemporaryObjectExpr final : public CXXConstructExpr {
  friend class ASTStmtReader;

  // CXXTemporaryObjectExpr has some trailing objects belonging
  // to CXXConstructExpr. See the comment inside CXXConstructExpr
  // for more details.

  TypeSourceInfo *TSI;

  CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty,
                         TypeSourceInfo *TSI, ArrayRef<Expr *> Args,
                         SourceRange ParenOrBraceRange,
                         bool HadMultipleCandidates, bool ListInitialization,
                         bool StdInitListInitialization,
                         bool ZeroInitialization);

  CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs);

public:
  static CXXTemporaryObjectExpr *
  Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty,
         TypeSourceInfo *TSI, ArrayRef<Expr *> Args,
         SourceRange ParenOrBraceRange, bool HadMultipleCandidates,
         bool ListInitialization, bool StdInitListInitialization,
         bool ZeroInitialization);

  static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx,
                                             unsigned NumArgs);

  TypeSourceInfo *getTypeSourceInfo() const { return TSI; }

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY;

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXTemporaryObjectExprClass;
  }
};

Stmt **CXXConstructExpr::getTrailingArgs() {
  if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this))
    return reinterpret_cast<Stmt **>(E + 1);
  assert((getStmtClass() == CXXConstructExprClass) &&
         "Unexpected class deriving from CXXConstructExpr!");
  return reinterpret_cast<Stmt **>(this + 1);
}

/// A C++ lambda expression, which produces a function object
/// (of unspecified type) that can be invoked later.
///
/// Example:
/// \code
/// void low_pass_filter(std::vector<double> &values, double cutoff) {
///   values.erase(std::remove_if(values.begin(), values.end(),
///                               [=](double value) { return value > cutoff; });
/// }
/// \endcode
///
/// C++11 lambda expressions can capture local variables, either by copying
/// the values of those local variables at the time the function
/// object is constructed (not when it is called!) or by holding a
/// reference to the local variable. These captures can occur either
/// implicitly or can be written explicitly between the square
/// brackets ([...]) that start the lambda expression.
///
/// C++1y introduces a new form of "capture" called an init-capture that
/// includes an initializing expression (rather than capturing a variable),
/// and which can never occur implicitly.
class LambdaExpr final : public Expr,
                         private llvm::TrailingObjects<LambdaExpr, Stmt *> {
  // LambdaExpr has some data stored in LambdaExprBits.

  /// The source range that covers the lambda introducer ([...]).
  SourceRange IntroducerRange;

  /// The source location of this lambda's capture-default ('=' or '&').
  SourceLocation CaptureDefaultLoc;

  /// The location of the closing brace ('}') that completes
  /// the lambda.
  ///
  /// The location of the brace is also available by looking up the
  /// function call operator in the lambda class. However, it is
  /// stored here to improve the performance of getSourceRange(), and
  /// to avoid having to deserialize the function call operator from a
  /// module file just to determine the source range.
  SourceLocation ClosingBrace;

  /// Construct a lambda expression.
  LambdaExpr(QualType T, SourceRange IntroducerRange,
             LambdaCaptureDefault CaptureDefault,
             SourceLocation CaptureDefaultLoc, bool ExplicitParams,
             bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
             SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack);

  /// Construct an empty lambda expression.
  LambdaExpr(EmptyShell Empty, unsigned NumCaptures);

  Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
  Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }

  void initBodyIfNeeded() const;

public:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// Construct a new lambda expression.
  static LambdaExpr *
  Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
         LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
         bool ExplicitParams, bool ExplicitResultType,
         ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace,
         bool ContainsUnexpandedParameterPack);

  /// Construct a new lambda expression that will be deserialized from
  /// an external source.
  static LambdaExpr *CreateDeserialized(const ASTContext &C,
                                        unsigned NumCaptures);

  /// Determine the default capture kind for this lambda.
  LambdaCaptureDefault getCaptureDefault() const {
    return static_cast<LambdaCaptureDefault>(LambdaExprBits.CaptureDefault);
  }

  /// Retrieve the location of this lambda's capture-default, if any.
  SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; }

  /// Determine whether one of this lambda's captures is an init-capture.
  bool isInitCapture(const LambdaCapture *Capture) const;

  /// An iterator that walks over the captures of the lambda,
  /// both implicit and explicit.
  using capture_iterator = const LambdaCapture *;

  /// An iterator over a range of lambda captures.
  using capture_range = llvm::iterator_range<capture_iterator>;

  /// Retrieve this lambda's captures.
  capture_range captures() const;

  /// Retrieve an iterator pointing to the first lambda capture.
  capture_iterator capture_begin() const;

  /// Retrieve an iterator pointing past the end of the
  /// sequence of lambda captures.
  capture_iterator capture_end() const;

  /// Determine the number of captures in this lambda.
  unsigned capture_size() const { return LambdaExprBits.NumCaptures; }

  /// Retrieve this lambda's explicit captures.
  capture_range explicit_captures() const;

  /// Retrieve an iterator pointing to the first explicit
  /// lambda capture.
  capture_iterator explicit_capture_begin() const;

  /// Retrieve an iterator pointing past the end of the sequence of
  /// explicit lambda captures.
  capture_iterator explicit_capture_end() const;

  /// Retrieve this lambda's implicit captures.
  capture_range implicit_captures() const;

  /// Retrieve an iterator pointing to the first implicit
  /// lambda capture.
  capture_iterator implicit_capture_begin() const;

  /// Retrieve an iterator pointing past the end of the sequence of
  /// implicit lambda captures.
  capture_iterator implicit_capture_end() const;

  /// Iterator that walks over the capture initialization
  /// arguments.
  using capture_init_iterator = Expr **;

  /// Const iterator that walks over the capture initialization
  /// arguments.
  /// FIXME: This interface is prone to being used incorrectly.
  using const_capture_init_iterator = Expr *const *;

  /// Retrieve the initialization expressions for this lambda's captures.
  llvm::iterator_range<capture_init_iterator> capture_inits() {
    return llvm::make_range(capture_init_begin(), capture_init_end());
  }

  /// Retrieve the initialization expressions for this lambda's captures.
  llvm::iterator_range<const_capture_init_iterator> capture_inits() const {
    return llvm::make_range(capture_init_begin(), capture_init_end());
  }

  /// Retrieve the first initialization argument for this
  /// lambda expression (which initializes the first capture field).
  capture_init_iterator capture_init_begin() {
    return reinterpret_cast<Expr **>(getStoredStmts());
  }

  /// Retrieve the first initialization argument for this
  /// lambda expression (which initializes the first capture field).
  const_capture_init_iterator capture_init_begin() const {
    return reinterpret_cast<Expr *const *>(getStoredStmts());
  }

  /// Retrieve the iterator pointing one past the last
  /// initialization argument for this lambda expression.
  capture_init_iterator capture_init_end() {
    return capture_init_begin() + capture_size();
  }

  /// Retrieve the iterator pointing one past the last
  /// initialization argument for this lambda expression.
  const_capture_init_iterator capture_init_end() const {
    return capture_init_begin() + capture_size();
  }

  /// Retrieve the source range covering the lambda introducer,
  /// which contains the explicit capture list surrounded by square
  /// brackets ([...]).
  SourceRange getIntroducerRange() const { return IntroducerRange; }

  /// Retrieve the class that corresponds to the lambda.
  ///
  /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the
  /// captures in its fields and provides the various operations permitted
  /// on a lambda (copying, calling).
  CXXRecordDecl *getLambdaClass() const;

  /// Retrieve the function call operator associated with this
  /// lambda expression.
  CXXMethodDecl *getCallOperator() const;

  /// Retrieve the function template call operator associated with this
  /// lambda expression.
  FunctionTemplateDecl *getDependentCallOperator() const;

  /// If this is a generic lambda expression, retrieve the template
  /// parameter list associated with it, or else return null.
  TemplateParameterList *getTemplateParameterList() const;

  /// Get the template parameters were explicitly specified (as opposed to being
  /// invented by use of an auto parameter).
  ArrayRef<NamedDecl *> getExplicitTemplateParameters() const;

  /// Whether this is a generic lambda.
  bool isGenericLambda() const { return getTemplateParameterList(); }

  /// Retrieve the body of the lambda. This will be most of the time
  /// a \p CompoundStmt, but can also be \p CoroutineBodyStmt wrapping
  /// a \p CompoundStmt. Note that unlike functions, lambda-expressions
  /// cannot have a function-try-block.
  Stmt *getBody() const;

  /// Retrieve the \p CompoundStmt representing the body of the lambda.
  /// This is a convenience function for callers who do not need
  /// to handle node(s) which may wrap a \p CompoundStmt.
  const CompoundStmt *getCompoundStmtBody() const;
  CompoundStmt *getCompoundStmtBody() {
    const auto *ConstThis = this;
    return const_cast<CompoundStmt *>(ConstThis->getCompoundStmtBody());
  }

  /// Determine whether the lambda is mutable, meaning that any
  /// captures values can be modified.
  bool isMutable() const;

  /// Determine whether this lambda has an explicit parameter
  /// list vs. an implicit (empty) parameter list.
  bool hasExplicitParameters() const { return LambdaExprBits.ExplicitParams; }

  /// Whether this lambda had its result type explicitly specified.
  bool hasExplicitResultType() const {
    return LambdaExprBits.ExplicitResultType;
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == LambdaExprClass;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return IntroducerRange.getBegin();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; }

  /// Includes the captures and the body of the lambda.
  child_range children();
  const_child_range children() const;
};

/// An expression "T()" which creates a value-initialized rvalue of type
/// T, which is a non-class type.  See (C++98 [5.2.3p2]).
class CXXScalarValueInitExpr : public Expr {
  friend class ASTStmtReader;

  TypeSourceInfo *TypeInfo;

public:
  /// Create an explicitly-written scalar-value initialization
  /// expression.
  CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
                         SourceLocation RParenLoc)
      : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary),
        TypeInfo(TypeInfo) {
    CXXScalarValueInitExprBits.RParenLoc = RParenLoc;
    setDependence(computeDependence(this));
  }

  explicit CXXScalarValueInitExpr(EmptyShell Shell)
      : Expr(CXXScalarValueInitExprClass, Shell) {}

  TypeSourceInfo *getTypeSourceInfo() const {
    return TypeInfo;
  }

  SourceLocation getRParenLoc() const {
    return CXXScalarValueInitExprBits.RParenLoc;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const { return getRParenLoc(); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXScalarValueInitExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// Points to the allocation function used.
  FunctionDecl *OperatorNew;

  /// Points to the deallocation function used in case of error. May be null.
  FunctionDecl *OperatorDelete;

  /// The allocated type-source information, as written in the source.
  TypeSourceInfo *AllocatedTypeInfo;

  /// Range of the entire new expression.
  SourceRange Range;

  /// Source-range of a paren-delimited initializer.
  SourceRange DirectInitRange;

  // CXXNewExpr is followed by several optional trailing objects.
  // They are in order:
  //
  // * An optional "Stmt *" for the array size expression.
  //    Present if and ony if isArray().
  //
  // * An optional "Stmt *" for the init expression.
  //    Present if and only if hasInitializer().
  //
  // * An array of getNumPlacementArgs() "Stmt *" for the placement new
  //   arguments, if any.
  //
  // * An optional SourceRange for the range covering the parenthesized type-id
  //    if the allocated type was expressed as a parenthesized type-id.
  //    Present if and only if isParenTypeId().
  unsigned arraySizeOffset() const { return 0; }
  unsigned initExprOffset() const { return arraySizeOffset() + isArray(); }
  unsigned placementNewArgsOffset() const {
    return initExprOffset() + hasInitializer();
  }

  unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
    return isArray() + hasInitializer() + getNumPlacementArgs();
  }

  unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
    return isParenTypeId();
  }

public:
  enum InitializationStyle {
    /// New-expression has no initializer as written.
    NoInit,

    /// New-expression has a C++98 paren-delimited initializer.
    CallInit,

    /// New-expression has a C++11 list-initializer.
    ListInit
  };

private:
  /// Build a c++ new expression.
  CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
             FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
             bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
             SourceRange TypeIdParens, Optional<Expr *> ArraySize,
             InitializationStyle InitializationStyle, Expr *Initializer,
             QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
             SourceRange DirectInitRange);

  /// Build an empty c++ new expression.
  CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs,
             bool IsParenTypeId);

public:
  /// Create a c++ new expression.
  static CXXNewExpr *
  Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew,
         FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
         bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
         SourceRange TypeIdParens, Optional<Expr *> ArraySize,
         InitializationStyle InitializationStyle, Expr *Initializer,
         QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
         SourceRange DirectInitRange);

  /// Create an empty c++ new expression.
  static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray,
                                 bool HasInit, unsigned NumPlacementArgs,
                                 bool IsParenTypeId);

  QualType getAllocatedType() const {
    return getType()->castAs<PointerType>()->getPointeeType();
  }

  TypeSourceInfo *getAllocatedTypeSourceInfo() const {
    return AllocatedTypeInfo;
  }

  /// True if the allocation result needs to be null-checked.
  ///
  /// C++11 [expr.new]p13:
  ///   If the allocation function returns null, initialization shall
  ///   not be done, the deallocation function shall not be called,
  ///   and the value of the new-expression shall be null.
  ///
  /// C++ DR1748:
  ///   If the allocation function is a reserved placement allocation
  ///   function that returns null, the behavior is undefined.
  ///
  /// An allocation function is not allowed to return null unless it
  /// has a non-throwing exception-specification.  The '03 rule is
  /// identical except that the definition of a non-throwing
  /// exception specification is just "is it throw()?".
  bool shouldNullCheckAllocation() const;

  FunctionDecl *getOperatorNew() const { return OperatorNew; }
  void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
  FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
  void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }

  bool isArray() const { return CXXNewExprBits.IsArray; }

  Optional<Expr *> getArraySize() {
    if (!isArray())
      return None;
    return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
  }
  Optional<const Expr *> getArraySize() const {
    if (!isArray())
      return None;
    return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
  }

  unsigned getNumPlacementArgs() const {
    return CXXNewExprBits.NumPlacementArgs;
  }

  Expr **getPlacementArgs() {
    return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() +
                                     placementNewArgsOffset());
  }

  Expr *getPlacementArg(unsigned I) {
    assert((I < getNumPlacementArgs()) && "Index out of range!");
    return getPlacementArgs()[I];
  }
  const Expr *getPlacementArg(unsigned I) const {
    return const_cast<CXXNewExpr *>(this)->getPlacementArg(I);
  }

  bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; }
  SourceRange getTypeIdParens() const {
    return isParenTypeId() ? getTrailingObjects<SourceRange>()[0]
                           : SourceRange();
  }

  bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; }

  /// Whether this new-expression has any initializer at all.
  bool hasInitializer() const {
    return CXXNewExprBits.StoredInitializationStyle > 0;
  }

  /// The kind of initializer this new-expression has.
  InitializationStyle getInitializationStyle() const {
    if (CXXNewExprBits.StoredInitializationStyle == 0)
      return NoInit;
    return static_cast<InitializationStyle>(
        CXXNewExprBits.StoredInitializationStyle - 1);
  }

  /// The initializer of this new-expression.
  Expr *getInitializer() {
    return hasInitializer()
               ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()])
               : nullptr;
  }
  const Expr *getInitializer() const {
    return hasInitializer()
               ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()])
               : nullptr;
  }

  /// Returns the CXXConstructExpr from this new-expression, or null.
  const CXXConstructExpr *getConstructExpr() const {
    return dyn_cast_or_null<CXXConstructExpr>(getInitializer());
  }

  /// Indicates whether the required alignment should be implicitly passed to
  /// the allocation function.
  bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; }

  /// Answers whether the usual array deallocation function for the
  /// allocated type expects the size of the allocation as a
  /// parameter.
  bool doesUsualArrayDeleteWantSize() const {
    return CXXNewExprBits.UsualArrayDeleteWantsSize;
  }

  using arg_iterator = ExprIterator;
  using const_arg_iterator = ConstExprIterator;

  llvm::iterator_range<arg_iterator> placement_arguments() {
    return llvm::make_range(placement_arg_begin(), placement_arg_end());
  }

  llvm::iterator_range<const_arg_iterator> placement_arguments() const {
    return llvm::make_range(placement_arg_begin(), placement_arg_end());
  }

  arg_iterator placement_arg_begin() {
    return getTrailingObjects<Stmt *>() + placementNewArgsOffset();
  }
  arg_iterator placement_arg_end() {
    return placement_arg_begin() + getNumPlacementArgs();
  }
  const_arg_iterator placement_arg_begin() const {
    return getTrailingObjects<Stmt *>() + placementNewArgsOffset();
  }
  const_arg_iterator placement_arg_end() const {
    return placement_arg_begin() + getNumPlacementArgs();
  }

  using raw_arg_iterator = Stmt **;

  raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); }
  raw_arg_iterator raw_arg_end() {
    return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>());
  }
  const_arg_iterator raw_arg_begin() const {
    return getTrailingObjects<Stmt *>();
  }
  const_arg_iterator raw_arg_end() const {
    return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>());
  }

  SourceLocation getBeginLoc() const { return Range.getBegin(); }
  SourceLocation getEndLoc() const { return Range.getEnd(); }

  SourceRange getDirectInitRange() const { return DirectInitRange; }
  SourceRange getSourceRange() const { return Range; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXNewExprClass;
  }

  // Iterators
  child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); }

  const_child_range children() const {
    return const_child_range(const_cast<CXXNewExpr *>(this)->children());
  }
};

/// Represents a \c delete expression for memory deallocation and
/// destructor calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
  friend class ASTStmtReader;

  /// Points to the operator delete overload that is used. Could be a member.
  FunctionDecl *OperatorDelete = nullptr;

  /// The pointer expression to be deleted.
  Stmt *Argument = nullptr;

public:
  CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm,
                bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize,
                FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc)
      : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary),
        OperatorDelete(OperatorDelete), Argument(Arg) {
    CXXDeleteExprBits.GlobalDelete = GlobalDelete;
    CXXDeleteExprBits.ArrayForm = ArrayForm;
    CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten;
    CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
    CXXDeleteExprBits.Loc = Loc;
    setDependence(computeDependence(this));
  }

  explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {}

  bool isGlobalDelete() const { return CXXDeleteExprBits.GlobalDelete; }
  bool isArrayForm() const { return CXXDeleteExprBits.ArrayForm; }
  bool isArrayFormAsWritten() const {
    return CXXDeleteExprBits.ArrayFormAsWritten;
  }

  /// Answers whether the usual array deallocation function for the
  /// allocated type expects the size of the allocation as a
  /// parameter.  This can be true even if the actual deallocation
  /// function that we're using doesn't want a size.
  bool doesUsualArrayDeleteWantSize() const {
    return CXXDeleteExprBits.UsualArrayDeleteWantsSize;
  }

  FunctionDecl *getOperatorDelete() const { return OperatorDelete; }

  Expr *getArgument() { return cast<Expr>(Argument); }
  const Expr *getArgument() const { return cast<Expr>(Argument); }

  /// Retrieve the type being destroyed.
  ///
  /// If the type being destroyed is a dependent type which may or may not
  /// be a pointer, return an invalid type.
  QualType getDestroyedType() const;

  SourceLocation getBeginLoc() const { return CXXDeleteExprBits.Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY {
    return Argument->getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXDeleteExprClass;
  }

  // Iterators
  child_range children() { return child_range(&Argument, &Argument + 1); }

  const_child_range children() const {
    return const_child_range(&Argument, &Argument + 1);
  }
};

/// Stores the type being destroyed by a pseudo-destructor expression.
class PseudoDestructorTypeStorage {
  /// Either the type source information or the name of the type, if
  /// it couldn't be resolved due to type-dependence.
  llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;

  /// The starting source location of the pseudo-destructor type.
  SourceLocation Location;

public:
  PseudoDestructorTypeStorage() = default;

  PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
      : Type(II), Location(Loc) {}

  PseudoDestructorTypeStorage(TypeSourceInfo *Info);

  TypeSourceInfo *getTypeSourceInfo() const {
    return Type.dyn_cast<TypeSourceInfo *>();
  }

  IdentifierInfo *getIdentifier() const {
    return Type.dyn_cast<IdentifierInfo *>();
  }

  SourceLocation getLocation() const { return Location; }
};

/// Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
///
/// A pseudo-destructor is an expression that looks like a member access to a
/// destructor of a scalar type, except that scalar types don't have
/// destructors. For example:
///
/// \code
/// typedef int T;
/// void f(int *p) {
///   p->T::~T();
/// }
/// \endcode
///
/// Pseudo-destructors typically occur when instantiating templates such as:
///
/// \code
/// template<typename T>
/// void destroy(T* ptr) {
///   ptr->T::~T();
/// }
/// \endcode
///
/// for scalar types. A pseudo-destructor expression has no run-time semantics
/// beyond evaluating the base expression.
class CXXPseudoDestructorExpr : public Expr {
  friend class ASTStmtReader;

  /// The base expression (that is being destroyed).
  Stmt *Base = nullptr;

  /// Whether the operator was an arrow ('->'); otherwise, it was a
  /// period ('.').
  bool IsArrow : 1;

  /// The location of the '.' or '->' operator.
  SourceLocation OperatorLoc;

  /// The nested-name-specifier that follows the operator, if present.
  NestedNameSpecifierLoc QualifierLoc;

  /// The type that precedes the '::' in a qualified pseudo-destructor
  /// expression.
  TypeSourceInfo *ScopeType = nullptr;

  /// The location of the '::' in a qualified pseudo-destructor
  /// expression.
  SourceLocation ColonColonLoc;

  /// The location of the '~'.
  SourceLocation TildeLoc;

  /// The type being destroyed, or its name if we were unable to
  /// resolve the name.
  PseudoDestructorTypeStorage DestroyedType;

public:
  CXXPseudoDestructorExpr(const ASTContext &Context,
                          Expr *Base, bool isArrow, SourceLocation OperatorLoc,
                          NestedNameSpecifierLoc QualifierLoc,
                          TypeSourceInfo *ScopeType,
                          SourceLocation ColonColonLoc,
                          SourceLocation TildeLoc,
                          PseudoDestructorTypeStorage DestroyedType);

  explicit CXXPseudoDestructorExpr(EmptyShell Shell)
      : Expr(CXXPseudoDestructorExprClass, Shell), IsArrow(false) {}

  Expr *getBase() const { return cast<Expr>(Base); }

  /// Determines whether this member expression actually had
  /// a C++ nested-name-specifier prior to the name of the member, e.g.,
  /// x->Base::foo.
  bool hasQualifier() const { return QualifierLoc.hasQualifier(); }

  /// Retrieves the nested-name-specifier that qualifies the type name,
  /// with source-location information.
  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }

  /// If the member name was qualified, retrieves the
  /// nested-name-specifier that precedes the member name. Otherwise, returns
  /// null.
  NestedNameSpecifier *getQualifier() const {
    return QualifierLoc.getNestedNameSpecifier();
  }

  /// Determine whether this pseudo-destructor expression was written
  /// using an '->' (otherwise, it used a '.').
  bool isArrow() const { return IsArrow; }

  /// Retrieve the location of the '.' or '->' operator.
  SourceLocation getOperatorLoc() const { return OperatorLoc; }

  /// Retrieve the scope type in a qualified pseudo-destructor
  /// expression.
  ///
  /// Pseudo-destructor expressions can have extra qualification within them
  /// that is not part of the nested-name-specifier, e.g., \c p->T::~T().
  /// Here, if the object type of the expression is (or may be) a scalar type,
  /// \p T may also be a scalar type and, therefore, cannot be part of a
  /// nested-name-specifier. It is stored as the "scope type" of the pseudo-
  /// destructor expression.
  TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }

  /// Retrieve the location of the '::' in a qualified pseudo-destructor
  /// expression.
  SourceLocation getColonColonLoc() const { return ColonColonLoc; }

  /// Retrieve the location of the '~'.
  SourceLocation getTildeLoc() const { return TildeLoc; }

  /// Retrieve the source location information for the type
  /// being destroyed.
  ///
  /// This type-source information is available for non-dependent
  /// pseudo-destructor expressions and some dependent pseudo-destructor
  /// expressions. Returns null if we only have the identifier for a
  /// dependent pseudo-destructor expression.
  TypeSourceInfo *getDestroyedTypeInfo() const {
    return DestroyedType.getTypeSourceInfo();
  }

  /// In a dependent pseudo-destructor expression for which we do not
  /// have full type information on the destroyed type, provides the name
  /// of the destroyed type.
  IdentifierInfo *getDestroyedTypeIdentifier() const {
    return DestroyedType.getIdentifier();
  }

  /// Retrieve the type being destroyed.
  QualType getDestroyedType() const;

  /// Retrieve the starting location of the type being destroyed.
  SourceLocation getDestroyedTypeLoc() const {
    return DestroyedType.getLocation();
  }

  /// Set the name of destroyed type for a dependent pseudo-destructor
  /// expression.
  void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) {
    DestroyedType = PseudoDestructorTypeStorage(II, Loc);
  }

  /// Set the destroyed type.
  void setDestroyedType(TypeSourceInfo *Info) {
    DestroyedType = PseudoDestructorTypeStorage(Info);
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return Base->getBeginLoc();
  }
  SourceLocation getEndLoc() const LLVM_READONLY;

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXPseudoDestructorExprClass;
  }

  // Iterators
  child_range children() { return child_range(&Base, &Base + 1); }

  const_child_range children() const {
    return const_child_range(&Base, &Base + 1);
  }
};

/// A type trait used in the implementation of various C++11 and
/// Library TR1 trait templates.
///
/// \code
///   __is_pod(int) == true
///   __is_enum(std::string) == false
///   __is_trivially_constructible(vector<int>, int*, int*)
/// \endcode
class TypeTraitExpr final
    : public Expr,
      private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> {
  /// The location of the type trait keyword.
  SourceLocation Loc;

  ///  The location of the closing parenthesis.
  SourceLocation RParenLoc;

  // Note: The TypeSourceInfos for the arguments are allocated after the
  // TypeTraitExpr.

  TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
                ArrayRef<TypeSourceInfo *> Args,
                SourceLocation RParenLoc,
                bool Value);

  TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {}

  size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
    return getNumArgs();
  }

public:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// Create a new type trait expression.
  static TypeTraitExpr *Create(const ASTContext &C, QualType T,
                               SourceLocation Loc, TypeTrait Kind,
                               ArrayRef<TypeSourceInfo *> Args,
                               SourceLocation RParenLoc,
                               bool Value);

  static TypeTraitExpr *CreateDeserialized(const ASTContext &C,
                                           unsigned NumArgs);

  /// Determine which type trait this expression uses.
  TypeTrait getTrait() const {
    return static_cast<TypeTrait>(TypeTraitExprBits.Kind);
  }

  bool getValue() const {
    assert(!isValueDependent());
    return TypeTraitExprBits.Value;
  }

  /// Determine the number of arguments to this type trait.
  unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; }

  /// Retrieve the Ith argument.
  TypeSourceInfo *getArg(unsigned I) const {
    assert(I < getNumArgs() && "Argument out-of-range");
    return getArgs()[I];
  }

  /// Retrieve the argument types.
  ArrayRef<TypeSourceInfo *> getArgs() const {
    return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
                              getNumArgs());
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == TypeTraitExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// An Embarcadero array type trait, as used in the implementation of
/// __array_rank and __array_extent.
///
/// Example:
/// \code
///   __array_rank(int[10][20]) == 2
///   __array_extent(int, 1)    == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {
  /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
  unsigned ATT : 2;

  /// The value of the type trait. Unspecified if dependent.
  uint64_t Value = 0;

  /// The array dimension being queried, or -1 if not used.
  Expr *Dimension;

  /// The location of the type trait keyword.
  SourceLocation Loc;

  /// The location of the closing paren.
  SourceLocation RParen;

  /// The type being queried.
  TypeSourceInfo *QueriedType = nullptr;

public:
  friend class ASTStmtReader;

  ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att,
                     TypeSourceInfo *queried, uint64_t value, Expr *dimension,
                     SourceLocation rparen, QualType ty)
      : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary), ATT(att),
        Value(value), Dimension(dimension), Loc(loc), RParen(rparen),
        QueriedType(queried) {
    assert(att <= ATT_Last && "invalid enum value!");
    assert(static_cast<unsigned>(att) == ATT && "ATT overflow!");
    setDependence(computeDependence(this));
  }

  explicit ArrayTypeTraitExpr(EmptyShell Empty)
      : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {}

  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }

  ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); }

  QualType getQueriedType() const { return QueriedType->getType(); }

  TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }

  uint64_t getValue() const { assert(!isTypeDependent()); return Value; }

  Expr *getDimensionExpression() const { return Dimension; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ArrayTypeTraitExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// An expression trait intrinsic.
///
/// Example:
/// \code
///   __is_lvalue_expr(std::cout) == true
///   __is_lvalue_expr(1) == false
/// \endcode
class ExpressionTraitExpr : public Expr {
  /// The trait. A ExpressionTrait enum in MSVC compatible unsigned.
  unsigned ET : 31;

  /// The value of the type trait. Unspecified if dependent.
  unsigned Value : 1;

  /// The location of the type trait keyword.
  SourceLocation Loc;

  /// The location of the closing paren.
  SourceLocation RParen;

  /// The expression being queried.
  Expr* QueriedExpression = nullptr;

public:
  friend class ASTStmtReader;

  ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried,
                      bool value, SourceLocation rparen, QualType resultType)
      : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary),
        ET(et), Value(value), Loc(loc), RParen(rparen),
        QueriedExpression(queried) {
    assert(et <= ET_Last && "invalid enum value!");
    assert(static_cast<unsigned>(et) == ET && "ET overflow!");
    setDependence(computeDependence(this));
  }

  explicit ExpressionTraitExpr(EmptyShell Empty)
      : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {}

  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParen; }

  ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); }

  Expr *getQueriedExpression() const { return QueriedExpression; }

  bool getValue() const { return Value; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ExpressionTraitExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// A reference to an overloaded function set, either an
/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
class OverloadExpr : public Expr {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  /// The common name of these declarations.
  DeclarationNameInfo NameInfo;

  /// The nested-name-specifier that qualifies the name, if any.
  NestedNameSpecifierLoc QualifierLoc;

protected:
  OverloadExpr(StmtClass SC, const ASTContext &Context,
               NestedNameSpecifierLoc QualifierLoc,
               SourceLocation TemplateKWLoc,
               const DeclarationNameInfo &NameInfo,
               const TemplateArgumentListInfo *TemplateArgs,
               UnresolvedSetIterator Begin, UnresolvedSetIterator End,
               bool KnownDependent, bool KnownInstantiationDependent,
               bool KnownContainsUnexpandedParameterPack);

  OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults,
               bool HasTemplateKWAndArgsInfo);

  /// Return the results. Defined after UnresolvedMemberExpr.
  inline DeclAccessPair *getTrailingResults();
  const DeclAccessPair *getTrailingResults() const {
    return const_cast<OverloadExpr *>(this)->getTrailingResults();
  }

  /// Return the optional template keyword and arguments info.
  /// Defined after UnresolvedMemberExpr.
  inline ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo();
  const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const {
    return const_cast<OverloadExpr *>(this)
        ->getTrailingASTTemplateKWAndArgsInfo();
  }

  /// Return the optional template arguments. Defined after
  /// UnresolvedMemberExpr.
  inline TemplateArgumentLoc *getTrailingTemplateArgumentLoc();
  const TemplateArgumentLoc *getTrailingTemplateArgumentLoc() const {
    return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc();
  }

  bool hasTemplateKWAndArgsInfo() const {
    return OverloadExprBits.HasTemplateKWAndArgsInfo;
  }

public:
  struct FindResult {
    OverloadExpr *Expression;
    bool IsAddressOfOperand;
    bool HasFormOfMemberPointer;
  };

  /// Finds the overloaded expression in the given expression \p E of
  /// OverloadTy.
  ///
  /// \return the expression (which must be there) and true if it has
  /// the particular form of a member pointer expression
  static FindResult find(Expr *E) {
    assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));

    FindResult Result;

    E = E->IgnoreParens();
    if (isa<UnaryOperator>(E)) {
      assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
      E = cast<UnaryOperator>(E)->getSubExpr();
      auto *Ovl = cast<OverloadExpr>(E->IgnoreParens());

      Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
      Result.IsAddressOfOperand = true;
      Result.Expression = Ovl;
    } else {
      Result.HasFormOfMemberPointer = false;
      Result.IsAddressOfOperand = false;
      Result.Expression = cast<OverloadExpr>(E);
    }

    return Result;
  }

  /// Gets the naming class of this lookup, if any.
  /// Defined after UnresolvedMemberExpr.
  inline CXXRecordDecl *getNamingClass();
  const CXXRecordDecl *getNamingClass() const {
    return const_cast<OverloadExpr *>(this)->getNamingClass();
  }

  using decls_iterator = UnresolvedSetImpl::iterator;

  decls_iterator decls_begin() const {
    return UnresolvedSetIterator(getTrailingResults());
  }
  decls_iterator decls_end() const {
    return UnresolvedSetIterator(getTrailingResults() + getNumDecls());
  }
  llvm::iterator_range<decls_iterator> decls() const {
    return llvm::make_range(decls_begin(), decls_end());
  }

  /// Gets the number of declarations in the unresolved set.
  unsigned getNumDecls() const { return OverloadExprBits.NumResults; }

  /// Gets the full name info.
  const DeclarationNameInfo &getNameInfo() const { return NameInfo; }

  /// Gets the name looked up.
  DeclarationName getName() const { return NameInfo.getName(); }

  /// Gets the location of the name.
  SourceLocation getNameLoc() const { return NameInfo.getLoc(); }

  /// Fetches the nested-name qualifier, if one was given.
  NestedNameSpecifier *getQualifier() const {
    return QualifierLoc.getNestedNameSpecifier();
  }

  /// Fetches the nested-name qualifier with source-location
  /// information, if one was given.
  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }

  /// Retrieve the location of the template keyword preceding
  /// this name, if any.
  SourceLocation getTemplateKeywordLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc;
  }

  /// Retrieve the location of the left angle bracket starting the
  /// explicit template argument list following the name, if any.
  SourceLocation getLAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc;
  }

  /// Retrieve the location of the right angle bracket ending the
  /// explicit template argument list following the name, if any.
  SourceLocation getRAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc;
  }

  /// Determines whether the name was preceded by the template keyword.
  bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

  /// Determines whether this expression had explicit template arguments.
  bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }

  TemplateArgumentLoc const *getTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return nullptr;
    return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc();
  }

  unsigned getNumTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return 0;

    return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs;
  }

  ArrayRef<TemplateArgumentLoc> template_arguments() const {
    return {getTemplateArgs(), getNumTemplateArgs()};
  }

  /// Copies the template arguments into the given structure.
  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
    if (hasExplicitTemplateArgs())
      getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == UnresolvedLookupExprClass ||
           T->getStmtClass() == UnresolvedMemberExprClass;
  }
};

/// A reference to a name which we were able to look up during
/// parsing but could not resolve to a specific declaration.
///
/// This arises in several ways:
///   * we might be waiting for argument-dependent lookup;
///   * the name might resolve to an overloaded function;
/// and eventually:
///   * the lookup might have included a function template.
///
/// These never include UnresolvedUsingValueDecls, which are always class
/// members and therefore appear only in UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr final
    : public OverloadExpr,
      private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {
  friend class ASTStmtReader;
  friend class OverloadExpr;
  friend TrailingObjects;

  /// The naming class (C++ [class.access.base]p5) of the lookup, if
  /// any.  This can generally be recalculated from the context chain,
  /// but that can be fairly expensive for unqualified lookups.
  CXXRecordDecl *NamingClass;

  // UnresolvedLookupExpr is followed by several trailing objects.
  // They are in order:
  //
  // * An array of getNumResults() DeclAccessPair for the results. These are
  //   undesugared, which is to say, they may include UsingShadowDecls.
  //   Access is relative to the naming class.
  //
  // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
  //   template keyword and arguments. Present if and only if
  //   hasTemplateKWAndArgsInfo().
  //
  // * An array of getNumTemplateArgs() TemplateArgumentLoc containing
  //   location information for the explicitly specified template arguments.

  UnresolvedLookupExpr(const ASTContext &Context, CXXRecordDecl *NamingClass,
                       NestedNameSpecifierLoc QualifierLoc,
                       SourceLocation TemplateKWLoc,
                       const DeclarationNameInfo &NameInfo, bool RequiresADL,
                       bool Overloaded,
                       const TemplateArgumentListInfo *TemplateArgs,
                       UnresolvedSetIterator Begin, UnresolvedSetIterator End);

  UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults,
                       bool HasTemplateKWAndArgsInfo);

  unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
    return getNumDecls();
  }

  unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
    return hasTemplateKWAndArgsInfo();
  }

public:
  static UnresolvedLookupExpr *
  Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
         NestedNameSpecifierLoc QualifierLoc,
         const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
         UnresolvedSetIterator Begin, UnresolvedSetIterator End);

  static UnresolvedLookupExpr *
  Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
         NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
         const DeclarationNameInfo &NameInfo, bool RequiresADL,
         const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
         UnresolvedSetIterator End);

  static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context,
                                           unsigned NumResults,
                                           bool HasTemplateKWAndArgsInfo,
                                           unsigned NumTemplateArgs);

  /// True if this declaration should be extended by
  /// argument-dependent lookup.
  bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; }

  /// True if this lookup is overloaded.
  bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; }

  /// Gets the 'naming class' (in the sense of C++0x
  /// [class.access.base]p5) of the lookup.  This is the scope
  /// that was looked in to find these results.
  CXXRecordDecl *getNamingClass() { return NamingClass; }
  const CXXRecordDecl *getNamingClass() const { return NamingClass; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    if (NestedNameSpecifierLoc l = getQualifierLoc())
      return l.getBeginLoc();
    return getNameInfo().getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    if (hasExplicitTemplateArgs())
      return getRAngleLoc();
    return getNameInfo().getEndLoc();
  }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == UnresolvedLookupExprClass;
  }
};

/// A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// DependentScopeDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
/// this case, X<T>::value cannot resolve to a declaration because the
/// declaration will differ from one instantiation of X<T> to the
/// next. Therefore, DependentScopeDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
class DependentScopeDeclRefExpr final
    : public Expr,
      private llvm::TrailingObjects<DependentScopeDeclRefExpr,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The nested-name-specifier that qualifies this unresolved
  /// declaration name.
  NestedNameSpecifierLoc QualifierLoc;

  /// The name of the entity we will be referencing.
  DeclarationNameInfo NameInfo;

  DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc,
                            SourceLocation TemplateKWLoc,
                            const DeclarationNameInfo &NameInfo,
                            const TemplateArgumentListInfo *Args);

  size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
    return hasTemplateKWAndArgsInfo();
  }

  bool hasTemplateKWAndArgsInfo() const {
    return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo;
  }

public:
  static DependentScopeDeclRefExpr *
  Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
         SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
         const TemplateArgumentListInfo *TemplateArgs);

  static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context,
                                                bool HasTemplateKWAndArgsInfo,
                                                unsigned NumTemplateArgs);

  /// Retrieve the name that this expression refers to.
  const DeclarationNameInfo &getNameInfo() const { return NameInfo; }

  /// Retrieve the name that this expression refers to.
  DeclarationName getDeclName() const { return NameInfo.getName(); }

  /// Retrieve the location of the name within the expression.
  ///
  /// For example, in "X<T>::value" this is the location of "value".
  SourceLocation getLocation() const { return NameInfo.getLoc(); }

  /// Retrieve the nested-name-specifier that qualifies the
  /// name, with source location information.
  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }

  /// Retrieve the nested-name-specifier that qualifies this
  /// declaration.
  NestedNameSpecifier *getQualifier() const {
    return QualifierLoc.getNestedNameSpecifier();
  }

  /// Retrieve the location of the template keyword preceding
  /// this name, if any.
  SourceLocation getTemplateKeywordLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
  }

  /// Retrieve the location of the left angle bracket starting the
  /// explicit template argument list following the name, if any.
  SourceLocation getLAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
  }

  /// Retrieve the location of the right angle bracket ending the
  /// explicit template argument list following the name, if any.
  SourceLocation getRAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
  }

  /// Determines whether the name was preceded by the template keyword.
  bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

  /// Determines whether this lookup had explicit template arguments.
  bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }

  /// Copies the template arguments (if present) into the given
  /// structure.
  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
    if (hasExplicitTemplateArgs())
      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
          getTrailingObjects<TemplateArgumentLoc>(), List);
  }

  TemplateArgumentLoc const *getTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return nullptr;

    return getTrailingObjects<TemplateArgumentLoc>();
  }

  unsigned getNumTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return 0;

    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
  }

  ArrayRef<TemplateArgumentLoc> template_arguments() const {
    return {getTemplateArgs(), getNumTemplateArgs()};
  }

  /// Note: getBeginLoc() is the start of the whole DependentScopeDeclRefExpr,
  /// and differs from getLocation().getStart().
  SourceLocation getBeginLoc() const LLVM_READONLY {
    return QualifierLoc.getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    if (hasExplicitTemplateArgs())
      return getRAngleLoc();
    return getLocation();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == DependentScopeDeclRefExprClass;
  }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents an expression -- generally a full-expression -- that
/// introduces cleanups to be run at the end of the sub-expression's
/// evaluation.  The most common source of expression-introduced
/// cleanups is temporary objects in C++, but several other kinds of
/// expressions can create cleanups, including basically every
/// call in ARC that returns an Objective-C pointer.
///
/// This expression also tracks whether the sub-expression contains a
/// potentially-evaluated block literal.  The lifetime of a block
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
    : public FullExpr,
      private llvm::TrailingObjects<
          ExprWithCleanups,
          llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>> {
public:
  /// The type of objects that are kept in the cleanup.
  /// It's useful to remember the set of blocks and block-scoped compound
  /// literals; we could also remember the set of temporaries, but there's
  /// currently no need.
  using CleanupObject = llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>;

private:
  friend class ASTStmtReader;
  friend TrailingObjects;

  ExprWithCleanups(EmptyShell, unsigned NumObjects);
  ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
                   ArrayRef<CleanupObject> Objects);

public:
  static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty,
                                  unsigned numObjects);

  static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr,
                                  bool CleanupsHaveSideEffects,
                                  ArrayRef<CleanupObject> objects);

  ArrayRef<CleanupObject> getObjects() const {
    return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(),
                              getNumObjects());
  }

  unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }

  CleanupObject getObject(unsigned i) const {
    assert(i < getNumObjects() && "Index out of range");
    return getObjects()[i];
  }

  bool cleanupsHaveSideEffects() const {
    return ExprWithCleanupsBits.CleanupsHaveSideEffects;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return SubExpr->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return SubExpr->getEndLoc();
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ExprWithCleanupsClass;
  }

  // Iterators
  child_range children() { return child_range(&SubExpr, &SubExpr + 1); }

  const_child_range children() const {
    return const_child_range(&SubExpr, &SubExpr + 1);
  }
};

/// Describes an explicit type conversion that uses functional
/// notion but could not be resolved because one or more arguments are
/// type-dependent.
///
/// The explicit type conversions expressed by
/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>,
/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and
/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is
/// type-dependent. For example, this would occur in a template such
/// as:
///
/// \code
///   template<typename T, typename A1>
///   inline T make_a(const A1& a1) {
///     return T(a1);
///   }
/// \endcode
///
/// When the returned expression is instantiated, it may resolve to a
/// constructor call, conversion function call, or some kind of type
/// conversion.
class CXXUnresolvedConstructExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> {
  friend class ASTStmtReader;
  friend TrailingObjects;

  /// The type being constructed.
  TypeSourceInfo *TSI;

  /// The location of the left parentheses ('(').
  SourceLocation LParenLoc;

  /// The location of the right parentheses (')').
  SourceLocation RParenLoc;

  CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, SourceLocation LParenLoc,
                             ArrayRef<Expr *> Args, SourceLocation RParenLoc);

  CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
      : Expr(CXXUnresolvedConstructExprClass, Empty) {
    CXXUnresolvedConstructExprBits.NumArgs = NumArgs;
  }

public:
  static CXXUnresolvedConstructExpr *Create(const ASTContext &Context,
                                            TypeSourceInfo *Type,
                                            SourceLocation LParenLoc,
                                            ArrayRef<Expr *> Args,
                                            SourceLocation RParenLoc);

  static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context,
                                                 unsigned NumArgs);

  /// Retrieve the type that is being constructed, as specified
  /// in the source code.
  QualType getTypeAsWritten() const { return TSI->getType(); }

  /// Retrieve the type source information for the type being
  /// constructed.
  TypeSourceInfo *getTypeSourceInfo() const { return TSI; }

  /// Retrieve the location of the left parentheses ('(') that
  /// precedes the argument list.
  SourceLocation getLParenLoc() const { return LParenLoc; }
  void setLParenLoc(SourceLocation L) { LParenLoc = L; }

  /// Retrieve the location of the right parentheses (')') that
  /// follows the argument list.
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  /// Determine whether this expression models list-initialization.
  /// If so, there will be exactly one subexpression, which will be
  /// an InitListExpr.
  bool isListInitialization() const { return LParenLoc.isInvalid(); }

  /// Retrieve the number of arguments.
  unsigned arg_size() const { return CXXUnresolvedConstructExprBits.NumArgs; }

  using arg_iterator = Expr **;
  using arg_range = llvm::iterator_range<arg_iterator>;

  arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); }
  arg_iterator arg_end() { return arg_begin() + arg_size(); }
  arg_range arguments() { return arg_range(arg_begin(), arg_end()); }

  using const_arg_iterator = const Expr* const *;
  using const_arg_range = llvm::iterator_range<const_arg_iterator>;

  const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
  const_arg_iterator arg_end() const { return arg_begin() + arg_size(); }
  const_arg_range arguments() const {
    return const_arg_range(arg_begin(), arg_end());
  }

  Expr *getArg(unsigned I) {
    assert(I < arg_size() && "Argument index out-of-range");
    return arg_begin()[I];
  }

  const Expr *getArg(unsigned I) const {
    assert(I < arg_size() && "Argument index out-of-range");
    return arg_begin()[I];
  }

  void setArg(unsigned I, Expr *E) {
    assert(I < arg_size() && "Argument index out-of-range");
    arg_begin()[I] = E;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY {
    if (!RParenLoc.isValid() && arg_size() > 0)
      return getArg(arg_size() - 1)->getEndLoc();
    return RParenLoc;
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXUnresolvedConstructExprClass;
  }

  // Iterators
  child_range children() {
    auto **begin = reinterpret_cast<Stmt **>(arg_begin());
    return child_range(begin, begin + arg_size());
  }

  const_child_range children() const {
    auto **begin = reinterpret_cast<Stmt **>(
        const_cast<CXXUnresolvedConstructExpr *>(this)->arg_begin());
    return const_child_range(begin, begin + arg_size());
  }
};

/// Represents a C++ member access expression where the actual
/// member referenced could not be resolved because the base
/// expression or the member name was dependent.
///
/// Like UnresolvedMemberExprs, these can be either implicit or
/// explicit accesses.  It is only possible to get one of these with
/// an implicit access if a qualifier is provided.
class CXXDependentScopeMemberExpr final
    : public Expr,
      private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc, NamedDecl *> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The expression for the base pointer or class reference,
  /// e.g., the \c x in x.f.  Can be null in implicit accesses.
  Stmt *Base;

  /// The type of the base expression.  Never null, even for
  /// implicit accesses.
  QualType BaseType;

  /// The nested-name-specifier that precedes the member name, if any.
  /// FIXME: This could be in principle store as a trailing object.
  /// However the performance impact of doing so should be investigated first.
  NestedNameSpecifierLoc QualifierLoc;

  /// The member to which this member expression refers, which
  /// can be name, overloaded operator, or destructor.
  ///
  /// FIXME: could also be a template-id
  DeclarationNameInfo MemberNameInfo;

  // CXXDependentScopeMemberExpr is followed by several trailing objects,
  // some of which optional. They are in order:
  //
  // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
  //   template keyword and arguments. Present if and only if
  //   hasTemplateKWAndArgsInfo().
  //
  // * An array of getNumTemplateArgs() TemplateArgumentLoc containing location
  //   information for the explicitly specified template arguments.
  //
  // * An optional NamedDecl *. In a qualified member access expression such
  //   as t->Base::f, this member stores the resolves of name lookup in the
  //   context of the member access expression, to be used at instantiation
  //   time. Present if and only if hasFirstQualifierFoundInScope().

  bool hasTemplateKWAndArgsInfo() const {
    return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
  }

  bool hasFirstQualifierFoundInScope() const {
    return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
  }

  unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
    return hasTemplateKWAndArgsInfo();
  }

  unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
    return getNumTemplateArgs();
  }

  unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
    return hasFirstQualifierFoundInScope();
  }

  CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
                              QualType BaseType, bool IsArrow,
                              SourceLocation OperatorLoc,
                              NestedNameSpecifierLoc QualifierLoc,
                              SourceLocation TemplateKWLoc,
                              NamedDecl *FirstQualifierFoundInScope,
                              DeclarationNameInfo MemberNameInfo,
                              const TemplateArgumentListInfo *TemplateArgs);

  CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
                              bool HasFirstQualifierFoundInScope);

public:
  static CXXDependentScopeMemberExpr *
  Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
         SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
         SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
         DeclarationNameInfo MemberNameInfo,
         const TemplateArgumentListInfo *TemplateArgs);

  static CXXDependentScopeMemberExpr *
  CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
              unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);

  /// True if this is an implicit access, i.e. one in which the
  /// member being accessed was not written in the source.  The source
  /// location of the operator is invalid in this case.
  bool isImplicitAccess() const {
    if (!Base)
      return true;
    return cast<Expr>(Base)->isImplicitCXXThis();
  }

  /// Retrieve the base object of this member expressions,
  /// e.g., the \c x in \c x.m.
  Expr *getBase() const {
    assert(!isImplicitAccess());
    return cast<Expr>(Base);
  }

  QualType getBaseType() const { return BaseType; }

  /// Determine whether this member expression used the '->'
  /// operator; otherwise, it used the '.' operator.
  bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }

  /// Retrieve the location of the '->' or '.' operator.
  SourceLocation getOperatorLoc() const {
    return CXXDependentScopeMemberExprBits.OperatorLoc;
  }

  /// Retrieve the nested-name-specifier that qualifies the member name.
  NestedNameSpecifier *getQualifier() const {
    return QualifierLoc.getNestedNameSpecifier();
  }

  /// Retrieve the nested-name-specifier that qualifies the member
  /// name, with source location information.
  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }

  /// Retrieve the first part of the nested-name-specifier that was
  /// found in the scope of the member access expression when the member access
  /// was initially parsed.
  ///
  /// This function only returns a useful result when member access expression
  /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
  /// returned by this function describes what was found by unqualified name
  /// lookup for the identifier "Base" within the scope of the member access
  /// expression itself. At template instantiation time, this information is
  /// combined with the results of name lookup into the type of the object
  /// expression itself (the class type of x).
  NamedDecl *getFirstQualifierFoundInScope() const {
    if (!hasFirstQualifierFoundInScope())
      return nullptr;
    return *getTrailingObjects<NamedDecl *>();
  }

  /// Retrieve the name of the member that this expression refers to.
  const DeclarationNameInfo &getMemberNameInfo() const {
    return MemberNameInfo;
  }

  /// Retrieve the name of the member that this expression refers to.
  DeclarationName getMember() const { return MemberNameInfo.getName(); }

  // Retrieve the location of the name of the member that this
  // expression refers to.
  SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }

  /// Retrieve the location of the template keyword preceding the
  /// member name, if any.
  SourceLocation getTemplateKeywordLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
  }

  /// Retrieve the location of the left angle bracket starting the
  /// explicit template argument list following the member name, if any.
  SourceLocation getLAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
  }

  /// Retrieve the location of the right angle bracket ending the
  /// explicit template argument list following the member name, if any.
  SourceLocation getRAngleLoc() const {
    if (!hasTemplateKWAndArgsInfo())
      return SourceLocation();
    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
  }

  /// Determines whether the member name was preceded by the template keyword.
  bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

  /// Determines whether this member expression actually had a C++
  /// template argument list explicitly specified, e.g., x.f<int>.
  bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }

  /// Copies the template arguments (if present) into the given
  /// structure.
  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
    if (hasExplicitTemplateArgs())
      getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
          getTrailingObjects<TemplateArgumentLoc>(), List);
  }

  /// Retrieve the template arguments provided as part of this
  /// template-id.
  const TemplateArgumentLoc *getTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return nullptr;

    return getTrailingObjects<TemplateArgumentLoc>();
  }

  /// Retrieve the number of template arguments provided as part of this
  /// template-id.
  unsigned getNumTemplateArgs() const {
    if (!hasExplicitTemplateArgs())
      return 0;

    return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
  }

  ArrayRef<TemplateArgumentLoc> template_arguments() const {
    return {getTemplateArgs(), getNumTemplateArgs()};
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    if (!isImplicitAccess())
      return Base->getBeginLoc();
    if (getQualifier())
      return getQualifierLoc().getBeginLoc();
    return MemberNameInfo.getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    if (hasExplicitTemplateArgs())
      return getRAngleLoc();
    return MemberNameInfo.getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXDependentScopeMemberExprClass;
  }

  // Iterators
  child_range children() {
    if (isImplicitAccess())
      return child_range(child_iterator(), child_iterator());
    return child_range(&Base, &Base + 1);
  }

  const_child_range children() const {
    if (isImplicitAccess())
      return const_child_range(const_child_iterator(), const_child_iterator());
    return const_child_range(&Base, &Base + 1);
  }
};

/// Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions.
///
/// The member access may be explicit or implicit:
/// \code
///    struct A {
///      int a, b;
///      int explicitAccess() { return this->a + this->A::b; }
///      int implicitAccess() { return a + A::b; }
///    };
/// \endcode
///
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
/// DeclRefExpr, depending on whether the member is static.
class UnresolvedMemberExpr final
    : public OverloadExpr,
      private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {
  friend class ASTStmtReader;
  friend class OverloadExpr;
  friend TrailingObjects;

  /// The expression for the base pointer or class reference,
  /// e.g., the \c x in x.f.
  ///
  /// This can be null if this is an 'unbased' member expression.
  Stmt *Base;

  /// The type of the base expression; never null.
  QualType BaseType;

  /// The location of the '->' or '.' operator.
  SourceLocation OperatorLoc;

  // UnresolvedMemberExpr is followed by several trailing objects.
  // They are in order:
  //
  // * An array of getNumResults() DeclAccessPair for the results. These are
  //   undesugared, which is to say, they may include UsingShadowDecls.
  //   Access is relative to the naming class.
  //
  // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified
  //   template keyword and arguments. Present if and only if
  //   hasTemplateKWAndArgsInfo().
  //
  // * An array of getNumTemplateArgs() TemplateArgumentLoc containing
  //   location information for the explicitly specified template arguments.

  UnresolvedMemberExpr(const ASTContext &Context, bool HasUnresolvedUsing,
                       Expr *Base, QualType BaseType, bool IsArrow,
                       SourceLocation OperatorLoc,
                       NestedNameSpecifierLoc QualifierLoc,
                       SourceLocation TemplateKWLoc,
                       const DeclarationNameInfo &MemberNameInfo,
                       const TemplateArgumentListInfo *TemplateArgs,
                       UnresolvedSetIterator Begin, UnresolvedSetIterator End);

  UnresolvedMemberExpr(EmptyShell Empty, unsigned NumResults,
                       bool HasTemplateKWAndArgsInfo);

  unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
    return getNumDecls();
  }

  unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
    return hasTemplateKWAndArgsInfo();
  }

public:
  static UnresolvedMemberExpr *
  Create(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base,
         QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
         NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
         const DeclarationNameInfo &MemberNameInfo,
         const TemplateArgumentListInfo *TemplateArgs,
         UnresolvedSetIterator Begin, UnresolvedSetIterator End);

  static UnresolvedMemberExpr *CreateEmpty(const ASTContext &Context,
                                           unsigned NumResults,
                                           bool HasTemplateKWAndArgsInfo,
                                           unsigned NumTemplateArgs);

  /// True if this is an implicit access, i.e., one in which the
  /// member being accessed was not written in the source.
  ///
  /// The source location of the operator is invalid in this case.
  bool isImplicitAccess() const;

  /// Retrieve the base object of this member expressions,
  /// e.g., the \c x in \c x.m.
  Expr *getBase() {
    assert(!isImplicitAccess());
    return cast<Expr>(Base);
  }
  const Expr *getBase() const {
    assert(!isImplicitAccess());
    return cast<Expr>(Base);
  }

  QualType getBaseType() const { return BaseType; }

  /// Determine whether the lookup results contain an unresolved using
  /// declaration.
  bool hasUnresolvedUsing() const {
    return UnresolvedMemberExprBits.HasUnresolvedUsing;
  }

  /// Determine whether this member expression used the '->'
  /// operator; otherwise, it used the '.' operator.
  bool isArrow() const { return UnresolvedMemberExprBits.IsArrow; }

  /// Retrieve the location of the '->' or '.' operator.
  SourceLocation getOperatorLoc() const { return OperatorLoc; }

  /// Retrieve the naming class of this lookup.
  CXXRecordDecl *getNamingClass();
  const CXXRecordDecl *getNamingClass() const {
    return const_cast<UnresolvedMemberExpr *>(this)->getNamingClass();
  }

  /// Retrieve the full name info for the member that this expression
  /// refers to.
  const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }

  /// Retrieve the name of the member that this expression refers to.
  DeclarationName getMemberName() const { return getName(); }

  /// Retrieve the location of the name of the member that this
  /// expression refers to.
  SourceLocation getMemberLoc() const { return getNameLoc(); }

  /// Return the preferred location (the member name) for the arrow when
  /// diagnosing a problem with this expression.
  SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    if (!isImplicitAccess())
      return Base->getBeginLoc();
    if (NestedNameSpecifierLoc l = getQualifierLoc())
      return l.getBeginLoc();
    return getMemberNameInfo().getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    if (hasExplicitTemplateArgs())
      return getRAngleLoc();
    return getMemberNameInfo().getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == UnresolvedMemberExprClass;
  }

  // Iterators
  child_range children() {
    if (isImplicitAccess())
      return child_range(child_iterator(), child_iterator());
    return child_range(&Base, &Base + 1);
  }

  const_child_range children() const {
    if (isImplicitAccess())
      return const_child_range(const_child_iterator(), const_child_iterator());
    return const_child_range(&Base, &Base + 1);
  }
};

DeclAccessPair *OverloadExpr::getTrailingResults() {
  if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
    return ULE->getTrailingObjects<DeclAccessPair>();
  return cast<UnresolvedMemberExpr>(this)->getTrailingObjects<DeclAccessPair>();
}

ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {
  if (!hasTemplateKWAndArgsInfo())
    return nullptr;

  if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
    return ULE->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
  return cast<UnresolvedMemberExpr>(this)
      ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
}

TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
  if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
    return ULE->getTrailingObjects<TemplateArgumentLoc>();
  return cast<UnresolvedMemberExpr>(this)
      ->getTrailingObjects<TemplateArgumentLoc>();
}

CXXRecordDecl *OverloadExpr::getNamingClass() {
  if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this))
    return ULE->getNamingClass();
  return cast<UnresolvedMemberExpr>(this)->getNamingClass();
}

/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
/// result is a boolean constant.
class CXXNoexceptExpr : public Expr {
  friend class ASTStmtReader;

  Stmt *Operand;
  SourceRange Range;

public:
  CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
                  SourceLocation Keyword, SourceLocation RParen)
      : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary),
        Operand(Operand), Range(Keyword, RParen) {
    CXXNoexceptExprBits.Value = Val == CT_Cannot;
    setDependence(computeDependence(this, Val));
  }

  CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {}

  Expr *getOperand() const { return static_cast<Expr *>(Operand); }

  SourceLocation getBeginLoc() const { return Range.getBegin(); }
  SourceLocation getEndLoc() const { return Range.getEnd(); }
  SourceRange getSourceRange() const { return Range; }

  bool getValue() const { return CXXNoexceptExprBits.Value; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXNoexceptExprClass;
  }

  // Iterators
  child_range children() { return child_range(&Operand, &Operand + 1); }

  const_child_range children() const {
    return const_child_range(&Operand, &Operand + 1);
  }
};

/// Represents a C++11 pack expansion that produces a sequence of
/// expressions.
///
/// A pack expansion expression contains a pattern (which itself is an
/// expression) followed by an ellipsis. For example:
///
/// \code
/// template<typename F, typename ...Types>
/// void forward(F f, Types &&...args) {
///   f(static_cast<Types&&>(args)...);
/// }
/// \endcode
///
/// Here, the argument to the function object \c f is a pack expansion whose
/// pattern is \c static_cast<Types&&>(args). When the \c forward function
/// template is instantiated, the pack expansion will instantiate to zero or
/// or more function arguments to the function object \c f.
class PackExpansionExpr : public Expr {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  SourceLocation EllipsisLoc;

  /// The number of expansions that will be produced by this pack
  /// expansion expression, if known.
  ///
  /// When zero, the number of expansions is not known. Otherwise, this value
  /// is the number of expansions + 1.
  unsigned NumExpansions;

  Stmt *Pattern;

public:
  PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
                    Optional<unsigned> NumExpansions)
      : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
             Pattern->getObjectKind()),
        EllipsisLoc(EllipsisLoc),
        NumExpansions(NumExpansions ? *NumExpansions + 1 : 0),
        Pattern(Pattern) {
    setDependence(computeDependence(this));
  }

  PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}

  /// Retrieve the pattern of the pack expansion.
  Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }

  /// Retrieve the pattern of the pack expansion.
  const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }

  /// Retrieve the location of the ellipsis that describes this pack
  /// expansion.
  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }

  /// Determine the number of expansions that will be produced when
  /// this pack expansion is instantiated, if already known.
  Optional<unsigned> getNumExpansions() const {
    if (NumExpansions)
      return NumExpansions - 1;

    return None;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return Pattern->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return EllipsisLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == PackExpansionExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(&Pattern, &Pattern + 1);
  }

  const_child_range children() const {
    return const_child_range(&Pattern, &Pattern + 1);
  }
};

/// Represents an expression that computes the length of a parameter
/// pack.
///
/// \code
/// template<typename ...Types>
/// struct count {
///   static const unsigned value = sizeof...(Types);
/// };
/// \endcode
class SizeOfPackExpr final
    : public Expr,
      private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The location of the \c sizeof keyword.
  SourceLocation OperatorLoc;

  /// The location of the name of the parameter pack.
  SourceLocation PackLoc;

  /// The location of the closing parenthesis.
  SourceLocation RParenLoc;

  /// The length of the parameter pack, if known.
  ///
  /// When this expression is not value-dependent, this is the length of
  /// the pack. When the expression was parsed rather than instantiated
  /// (and thus is value-dependent), this is zero.
  ///
  /// After partial substitution into a sizeof...(X) expression (for instance,
  /// within an alias template or during function template argument deduction),
  /// we store a trailing array of partially-substituted TemplateArguments,
  /// and this is the length of that array.
  unsigned Length;

  /// The parameter pack.
  NamedDecl *Pack = nullptr;

  /// Create an expression that computes the length of
  /// the given parameter pack.
  SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
                 SourceLocation PackLoc, SourceLocation RParenLoc,
                 Optional<unsigned> Length,
                 ArrayRef<TemplateArgument> PartialArgs)
      : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary),
        OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
        Length(Length ? *Length : PartialArgs.size()), Pack(Pack) {
    assert((!Length || PartialArgs.empty()) &&
           "have partial args for non-dependent sizeof... expression");
    auto *Args = getTrailingObjects<TemplateArgument>();
    std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args);
    setDependence(Length ? ExprDependence::None
                         : ExprDependence::ValueInstantiation);
  }

  /// Create an empty expression.
  SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs)
      : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}

public:
  static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
                                NamedDecl *Pack, SourceLocation PackLoc,
                                SourceLocation RParenLoc,
                                Optional<unsigned> Length = None,
                                ArrayRef<TemplateArgument> PartialArgs = None);
  static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
                                            unsigned NumPartialArgs);

  /// Determine the location of the 'sizeof' keyword.
  SourceLocation getOperatorLoc() const { return OperatorLoc; }

  /// Determine the location of the parameter pack.
  SourceLocation getPackLoc() const { return PackLoc; }

  /// Determine the location of the right parenthesis.
  SourceLocation getRParenLoc() const { return RParenLoc; }

  /// Retrieve the parameter pack.
  NamedDecl *getPack() const { return Pack; }

  /// Retrieve the length of the parameter pack.
  ///
  /// This routine may only be invoked when the expression is not
  /// value-dependent.
  unsigned getPackLength() const {
    assert(!isValueDependent() &&
           "Cannot get the length of a value-dependent pack size expression");
    return Length;
  }

  /// Determine whether this represents a partially-substituted sizeof...
  /// expression, such as is produced for:
  ///
  ///   template<typename ...Ts> using X = int[sizeof...(Ts)];
  ///   template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>);
  bool isPartiallySubstituted() const {
    return isValueDependent() && Length;
  }

  /// Get
  ArrayRef<TemplateArgument> getPartialArguments() const {
    assert(isPartiallySubstituted());
    const auto *Args = getTrailingObjects<TemplateArgument>();
    return llvm::makeArrayRef(Args, Args + Length);
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == SizeOfPackExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents a reference to a non-type template parameter
/// that has been substituted with a template argument.
class SubstNonTypeTemplateParmExpr : public Expr {
  friend class ASTReader;
  friend class ASTStmtReader;

  /// The replaced parameter.
  NonTypeTemplateParmDecl *Param;

  /// The replacement expression.
  Stmt *Replacement;

  explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
      : Expr(SubstNonTypeTemplateParmExprClass, Empty) {}

public:
  SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
                               SourceLocation Loc,
                               NonTypeTemplateParmDecl *Param,
                               Expr *Replacement)
      : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
        Param(Param), Replacement(Replacement) {
    SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
    setDependence(computeDependence(this));
  }

  SourceLocation getNameLoc() const {
    return SubstNonTypeTemplateParmExprBits.NameLoc;
  }
  SourceLocation getBeginLoc() const { return getNameLoc(); }
  SourceLocation getEndLoc() const { return getNameLoc(); }

  Expr *getReplacement() const { return cast<Expr>(Replacement); }

  NonTypeTemplateParmDecl *getParameter() const { return Param; }

  static bool classof(const Stmt *s) {
    return s->getStmtClass() == SubstNonTypeTemplateParmExprClass;
  }

  // Iterators
  child_range children() { return child_range(&Replacement, &Replacement + 1); }

  const_child_range children() const {
    return const_child_range(&Replacement, &Replacement + 1);
  }
};

/// Represents a reference to a non-type template parameter pack that
/// has been substituted with a non-template argument pack.
///
/// When a pack expansion in the source code contains multiple parameter packs
/// and those parameter packs correspond to different levels of template
/// parameter lists, this node is used to represent a non-type template
/// parameter pack from an outer level, which has already had its argument pack
/// substituted but that still lives within a pack expansion that itself
/// could not be instantiated. When actually performing a substitution into
/// that pack expansion (e.g., when all template parameters have corresponding
/// arguments), this type will be replaced with the appropriate underlying
/// expression at the current pack substitution index.
class SubstNonTypeTemplateParmPackExpr : public Expr {
  friend class ASTReader;
  friend class ASTStmtReader;

  /// The non-type template parameter pack itself.
  NonTypeTemplateParmDecl *Param;

  /// A pointer to the set of template arguments that this
  /// parameter pack is instantiated with.
  const TemplateArgument *Arguments;

  /// The number of template arguments in \c Arguments.
  unsigned NumArguments;

  /// The location of the non-type template parameter pack reference.
  SourceLocation NameLoc;

  explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
      : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}

public:
  SubstNonTypeTemplateParmPackExpr(QualType T,
                                   ExprValueKind ValueKind,
                                   NonTypeTemplateParmDecl *Param,
                                   SourceLocation NameLoc,
                                   const TemplateArgument &ArgPack);

  /// Retrieve the non-type template parameter pack being substituted.
  NonTypeTemplateParmDecl *getParameterPack() const { return Param; }

  /// Retrieve the location of the parameter pack name.
  SourceLocation getParameterPackLocation() const { return NameLoc; }

  /// Retrieve the template argument pack containing the substituted
  /// template arguments.
  TemplateArgument getArgumentPack() const;

  SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
  }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents a reference to a function parameter pack or init-capture pack
/// that has been substituted but not yet expanded.
///
/// When a pack expansion contains multiple parameter packs at different levels,
/// this node is used to represent a function parameter pack at an outer level
/// which we have already substituted to refer to expanded parameters, but where
/// the containing pack expansion cannot yet be expanded.
///
/// \code
/// template<typename...Ts> struct S {
///   template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...));
/// };
/// template struct S<int, int>;
/// \endcode
class FunctionParmPackExpr final
    : public Expr,
      private llvm::TrailingObjects<FunctionParmPackExpr, VarDecl *> {
  friend class ASTReader;
  friend class ASTStmtReader;
  friend TrailingObjects;

  /// The function parameter pack which was referenced.
  VarDecl *ParamPack;

  /// The location of the function parameter pack reference.
  SourceLocation NameLoc;

  /// The number of expansions of this pack.
  unsigned NumParameters;

  FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
                       SourceLocation NameLoc, unsigned NumParams,
                       VarDecl *const *Params);

public:
  static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
                                      VarDecl *ParamPack,
                                      SourceLocation NameLoc,
                                      ArrayRef<VarDecl *> Params);
  static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
                                           unsigned NumParams);

  /// Get the parameter pack which this expression refers to.
  VarDecl *getParameterPack() const { return ParamPack; }

  /// Get the location of the parameter pack.
  SourceLocation getParameterPackLocation() const { return NameLoc; }

  /// Iterators over the parameters which the parameter pack expanded
  /// into.
  using iterator = VarDecl * const *;
  iterator begin() const { return getTrailingObjects<VarDecl *>(); }
  iterator end() const { return begin() + NumParameters; }

  /// Get the number of parameters in this parameter pack.
  unsigned getNumExpansions() const { return NumParameters; }

  /// Get an expansion of the parameter pack by index.
  VarDecl *getExpansion(unsigned I) const { return begin()[I]; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == FunctionParmPackExprClass;
  }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  const_child_range children() const {
    return const_child_range(const_child_iterator(), const_child_iterator());
  }
};

/// Represents a prvalue temporary that is written into memory so that
/// a reference can bind to it.
///
/// Prvalue expressions are materialized when they need to have an address
/// in memory for a reference to bind to. This happens when binding a
/// reference to the result of a conversion, e.g.,
///
/// \code
/// const int &r = 1.0;
/// \endcode
///
/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is
/// then materialized via a \c MaterializeTemporaryExpr, and the reference
/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues
/// (either an lvalue or an xvalue, depending on the kind of reference binding
/// to it), maintaining the invariant that references always bind to glvalues.
///
/// Reference binding and copy-elision can both extend the lifetime of a
/// temporary. When either happens, the expression will also track the
/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {
private:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  llvm::PointerUnion<Stmt *, LifetimeExtendedTemporaryDecl *> State;

public:
  MaterializeTemporaryExpr(QualType T, Expr *Temporary,
                           bool BoundToLvalueReference,
                           LifetimeExtendedTemporaryDecl *MTD = nullptr);

  MaterializeTemporaryExpr(EmptyShell Empty)
      : Expr(MaterializeTemporaryExprClass, Empty) {}

  /// Retrieve the temporary-generating subexpression whose value will
  /// be materialized into a glvalue.
  Expr *getSubExpr() const {
    return cast<Expr>(
        State.is<Stmt *>()
            ? State.get<Stmt *>()
            : State.get<LifetimeExtendedTemporaryDecl *>()->getTemporaryExpr());
  }

  /// Retrieve the storage duration for the materialized temporary.
  StorageDuration getStorageDuration() const {
    return State.is<Stmt *>() ? SD_FullExpression
                              : State.get<LifetimeExtendedTemporaryDecl *>()
                                    ->getStorageDuration();
  }

  /// Get the storage for the constant value of a materialized temporary
  /// of static storage duration.
  APValue *getOrCreateValue(bool MayCreate) const {
    assert(State.is<LifetimeExtendedTemporaryDecl *>() &&
           "the temporary has not been lifetime extended");
    return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue(
        MayCreate);
  }

  LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() {
    return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
  }
  const LifetimeExtendedTemporaryDecl *
  getLifetimeExtendedTemporaryDecl() const {
    return State.dyn_cast<LifetimeExtendedTemporaryDecl *>();
  }

  /// Get the declaration which triggered the lifetime-extension of this
  /// temporary, if any.
  ValueDecl *getExtendingDecl() {
    return State.is<Stmt *>() ? nullptr
                              : State.get<LifetimeExtendedTemporaryDecl *>()
                                    ->getExtendingDecl();
  }
  const ValueDecl *getExtendingDecl() const {
    return const_cast<MaterializeTemporaryExpr *>(this)->getExtendingDecl();
  }

  void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber);

  unsigned getManglingNumber() const {
    return State.is<Stmt *>() ? 0
                              : State.get<LifetimeExtendedTemporaryDecl *>()
                                    ->getManglingNumber();
  }

  /// Determine whether this materialized temporary is bound to an
  /// lvalue reference; otherwise, it's bound to an rvalue reference.
  bool isBoundToLvalueReference() const {
    return getValueKind() == VK_LValue;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return getSubExpr()->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return getSubExpr()->getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == MaterializeTemporaryExprClass;
  }

  // Iterators
  child_range children() {
    return State.is<Stmt *>()
               ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1)
               : State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr();
  }

  const_child_range children() const {
    return State.is<Stmt *>()
               ? const_child_range(State.getAddrOfPtr1(),
                                   State.getAddrOfPtr1() + 1)
               : const_cast<const LifetimeExtendedTemporaryDecl *>(
                     State.get<LifetimeExtendedTemporaryDecl *>())
                     ->childrenExpr();
  }
};

/// Represents a folding of a pack over an operator.
///
/// This expression is always dependent and represents a pack expansion of the
/// forms:
///
///    ( expr op ... )
///    ( ... op expr )
///    ( expr op ... op expr )
class CXXFoldExpr : public Expr {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  SourceLocation LParenLoc;
  SourceLocation EllipsisLoc;
  SourceLocation RParenLoc;
  // When 0, the number of expansions is not known. Otherwise, this is one more
  // than the number of expansions.
  unsigned NumExpansions;
  Stmt *SubExprs[2];
  BinaryOperatorKind Opcode;

public:
  CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS,
              BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS,
              SourceLocation RParenLoc, Optional<unsigned> NumExpansions)
      : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary), LParenLoc(LParenLoc),
        EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
        NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
    SubExprs[0] = LHS;
    SubExprs[1] = RHS;
    setDependence(computeDependence(this));
  }

  CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}

  Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); }
  Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); }

  /// Does this produce a right-associated sequence of operators?
  bool isRightFold() const {
    return getLHS() && getLHS()->containsUnexpandedParameterPack();
  }

  /// Does this produce a left-associated sequence of operators?
  bool isLeftFold() const { return !isRightFold(); }

  /// Get the pattern, that is, the operand that contains an unexpanded pack.
  Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); }

  /// Get the operand that doesn't contain a pack, for a binary fold.
  Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); }

  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
  BinaryOperatorKind getOperator() const { return Opcode; }

  Optional<unsigned> getNumExpansions() const {
    if (NumExpansions)
      return NumExpansions - 1;
    return None;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }

  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CXXFoldExprClass;
  }

  // Iterators
  child_range children() { return child_range(SubExprs, SubExprs + 2); }

  const_child_range children() const {
    return const_child_range(SubExprs, SubExprs + 2);
  }
};

/// Represents an expression that might suspend coroutine execution;
/// either a co_await or co_yield expression.
///
/// Evaluation of this expression first evaluates its 'ready' expression. If
/// that returns 'false':
///  -- execution of the coroutine is suspended
///  -- the 'suspend' expression is evaluated
///     -- if the 'suspend' expression returns 'false', the coroutine is
///        resumed
///     -- otherwise, control passes back to the resumer.
/// If the coroutine is not suspended, or when it is resumed, the 'resume'
/// expression is evaluated, and its result is the result of the overall
/// expression.
class CoroutineSuspendExpr : public Expr {
  friend class ASTStmtReader;

  SourceLocation KeywordLoc;

  enum SubExpr { Common, Ready, Suspend, Resume, Count };

  Stmt *SubExprs[SubExpr::Count];
  OpaqueValueExpr *OpaqueValue = nullptr;

public:
  CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
                       Expr *Ready, Expr *Suspend, Expr *Resume,
                       OpaqueValueExpr *OpaqueValue)
      : Expr(SC, Resume->getType(), Resume->getValueKind(),
             Resume->getObjectKind()),
        KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
    SubExprs[SubExpr::Common] = Common;
    SubExprs[SubExpr::Ready] = Ready;
    SubExprs[SubExpr::Suspend] = Suspend;
    SubExprs[SubExpr::Resume] = Resume;
    setDependence(computeDependence(this));
  }

  CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
                       Expr *Common)
      : Expr(SC, Ty, VK_RValue, OK_Ordinary), KeywordLoc(KeywordLoc) {
    assert(Common->isTypeDependent() && Ty->isDependentType() &&
           "wrong constructor for non-dependent co_await/co_yield expression");
    SubExprs[SubExpr::Common] = Common;
    SubExprs[SubExpr::Ready] = nullptr;
    SubExprs[SubExpr::Suspend] = nullptr;
    SubExprs[SubExpr::Resume] = nullptr;
    setDependence(computeDependence(this));
  }

  CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
    SubExprs[SubExpr::Common] = nullptr;
    SubExprs[SubExpr::Ready] = nullptr;
    SubExprs[SubExpr::Suspend] = nullptr;
    SubExprs[SubExpr::Resume] = nullptr;
  }

  SourceLocation getKeywordLoc() const { return KeywordLoc; }

  Expr *getCommonExpr() const {
    return static_cast<Expr*>(SubExprs[SubExpr::Common]);
  }

  /// getOpaqueValue - Return the opaque value placeholder.
  OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }

  Expr *getReadyExpr() const {
    return static_cast<Expr*>(SubExprs[SubExpr::Ready]);
  }

  Expr *getSuspendExpr() const {
    return static_cast<Expr*>(SubExprs[SubExpr::Suspend]);
  }

  Expr *getResumeExpr() const {
    return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return getCommonExpr()->getEndLoc();
  }

  child_range children() {
    return child_range(SubExprs, SubExprs + SubExpr::Count);
  }

  const_child_range children() const {
    return const_child_range(SubExprs, SubExprs + SubExpr::Count);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CoawaitExprClass ||
           T->getStmtClass() == CoyieldExprClass;
  }
};

/// Represents a 'co_await' expression.
class CoawaitExpr : public CoroutineSuspendExpr {
  friend class ASTStmtReader;

public:
  CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
              Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue,
              bool IsImplicit = false)
      : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
                             Suspend, Resume, OpaqueValue) {
    CoawaitBits.IsImplicit = IsImplicit;
  }

  CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand,
              bool IsImplicit = false)
      : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {
    CoawaitBits.IsImplicit = IsImplicit;
  }

  CoawaitExpr(EmptyShell Empty)
      : CoroutineSuspendExpr(CoawaitExprClass, Empty) {}

  Expr *getOperand() const {
    // FIXME: Dig out the actual operand or store it.
    return getCommonExpr();
  }

  bool isImplicit() const { return CoawaitBits.IsImplicit; }
  void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CoawaitExprClass;
  }
};

/// Represents a 'co_await' expression while the type of the promise
/// is dependent.
class DependentCoawaitExpr : public Expr {
  friend class ASTStmtReader;

  SourceLocation KeywordLoc;
  Stmt *SubExprs[2];

public:
  DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op,
                       UnresolvedLookupExpr *OpCoawait)
      : Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary),
        KeywordLoc(KeywordLoc) {
    // NOTE: A co_await expression is dependent on the coroutines promise
    // type and may be dependent even when the `Op` expression is not.
    assert(Ty->isDependentType() &&
           "wrong constructor for non-dependent co_await/co_yield expression");
    SubExprs[0] = Op;
    SubExprs[1] = OpCoawait;
    setDependence(computeDependence(this));
  }

  DependentCoawaitExpr(EmptyShell Empty)
      : Expr(DependentCoawaitExprClass, Empty) {}

  Expr *getOperand() const { return cast<Expr>(SubExprs[0]); }

  UnresolvedLookupExpr *getOperatorCoawaitLookup() const {
    return cast<UnresolvedLookupExpr>(SubExprs[1]);
  }

  SourceLocation getKeywordLoc() const { return KeywordLoc; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return getOperand()->getEndLoc();
  }

  child_range children() { return child_range(SubExprs, SubExprs + 2); }

  const_child_range children() const {
    return const_child_range(SubExprs, SubExprs + 2);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == DependentCoawaitExprClass;
  }
};

/// Represents a 'co_yield' expression.
class CoyieldExpr : public CoroutineSuspendExpr {
  friend class ASTStmtReader;

public:
  CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
              Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue)
      : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
                             Suspend, Resume, OpaqueValue) {}
  CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
      : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
  CoyieldExpr(EmptyShell Empty)
      : CoroutineSuspendExpr(CoyieldExprClass, Empty) {}

  Expr *getOperand() const {
    // FIXME: Dig out the actual operand or store it.
    return getCommonExpr();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CoyieldExprClass;
  }
};

/// Represents a C++2a __builtin_bit_cast(T, v) expression. Used to implement
/// std::bit_cast. These can sometimes be evaluated as part of a constant
/// expression, but otherwise CodeGen to a simple memcpy in general.
class BuiltinBitCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<BuiltinBitCastExpr, CXXBaseSpecifier *> {
  friend class ASTStmtReader;
  friend class CastExpr;
  friend class TrailingObjects;

  SourceLocation KWLoc;
  SourceLocation RParenLoc;

public:
  BuiltinBitCastExpr(QualType T, ExprValueKind VK, CastKind CK, Expr *SrcExpr,
                     TypeSourceInfo *DstType, SourceLocation KWLoc,
                     SourceLocation RParenLoc)
      : ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0,
                         DstType),
        KWLoc(KWLoc), RParenLoc(RParenLoc) {}
  BuiltinBitCastExpr(EmptyShell Empty)
      : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0) {}

  SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == BuiltinBitCastExprClass;
  }
};

} // namespace clang

#endif // LLVM_CLANG_AST_EXPRCXX_H
