//===- 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;

  // 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, bool HasFPFeatures, 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, bool HasFPFeatures,
                                          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;
  }
};

/// 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,
                    FPOptionsOverride FPOptions, unsigned MinNumArgs);

  CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);

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

  static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
                                        bool HasFPFeatures, 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,
                     FPOptionsOverride FPFeatures, unsigned MinNumArgs);

  CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);

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

  static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx,
                                         unsigned NumArgs, bool HasFPFeatures,
                                         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; }
  BinaryOperatorKind getOpcode() const { return getOperator(); }
  static StringRef getOpcodeStr(BinaryOperatorKind Op) {
    return BinaryOperator::getOpcodeStr(Op);
  }
  StringRef getOpcodeStr() const {
    return BinaryOperator::getOpcodeStr(getOpcode());
  }
  bool isComparisonOp() const { return true; }
  bool isAssignmentOp() const { return false; }

  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, bool HasFPFeatures,
                   TypeSourceInfo *writtenTy, SourceLocation l,
                   SourceLocation RParenLoc, SourceRange AngleBrackets)
      : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, HasFPFeatures,
                         writtenTy),
        Loc(l), RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}

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

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 *,
                                    FPOptionsOverride> {
  CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
                    unsigned pathSize, TypeSourceInfo *writtenTy,
                    FPOptionsOverride FPO, SourceLocation l,
                    SourceLocation RParenLoc, SourceRange AngleBrackets)
      : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
                         FPO.requiresTrailingStorage(), writtenTy, l, RParenLoc,
                         AngleBrackets) {
    if (hasStoredFPFeatures())
      *getTrailingFPFeatures() = FPO;
  }

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

  unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const {
    return path_size();
  }

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,
         FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc,
         SourceRange AngleBrackets);
  static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context,
                                        unsigned PathSize, bool hasFPFeatures);

  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,
                         /*HasFPFeatures*/ false, writtenTy, l, RParenLoc,
                         AngleBrackets) {}

  explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
      : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize,
                         /*HasFPFeatures*/ false) {}

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, /*HasFPFeatures*/ false, writtenTy, l,
                         RParenLoc, AngleBrackets) {}

  CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
      : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize,
                         /*HasFPFeatures*/ false) {}

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,
                         /*HasFPFeatures*/ false, writtenTy, l, RParenLoc,
                         AngleBrackets) {}

  explicit CXXConstCastExpr(EmptyShell Empty)
      : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0,
                         /*HasFPFeatures*/ false) {}

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,
                         /*HasFPFeatures*/ false, writtenTy, l, RParenLoc,
                         AngleBrackets) {}

  explicit CXXAddrspaceCastExpr(EmptyShell Empty)
      : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0,
                         /*HasFPFeatures*/ false) {}

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, FPOptionsOverride FPFeatures);

  UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);

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

  static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx,
                                         unsigned NumArgs, bool HasFPOptions,
                                         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_PRValue, 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_PRValue, 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_PRValue, 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;

  /// Best-effort check if the expression operand refers to a most derived
  /// object. This is not a strong guarantee.
  bool isMostDerived(ASTContext &Context) 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_PRValue, 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_PRValue, 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(computeDependence(this));
  }

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_PRValue,
             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_PRValue, 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 *,
                                    FPOptionsOverride> {
  SourceLocation LParenLoc;
  SourceLocation RParenLoc;

  CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
                        TypeSourceInfo *writtenTy, CastKind kind,
                        Expr *castExpr, unsigned pathSize,
                        FPOptionsOverride FPO, SourceLocation lParenLoc,
                        SourceLocation rParenLoc)
      : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr,
                         pathSize, FPO.requiresTrailingStorage(), writtenTy),
        LParenLoc(lParenLoc), RParenLoc(rParenLoc) {
    if (hasStoredFPFeatures())
      *getTrailingFPFeatures() = FPO;
  }

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

  unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const {
    return path_size();
  }

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, FPOptionsOverride FPO, SourceLocation LPLoc,
         SourceLocation RPLoc);
  static CXXFunctionalCastExpr *
  CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures);

  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;

  /// Get the trailing requires clause, if any.
  Expr *getTrailingRequiresClause() 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_PRValue, 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; }

  /// This might return None even if isArray() returns true,
  /// since there might not be an array size expression.
  /// If the result is not-None, it will never wrap a nullptr.
  Optional<Expr *> getArraySize() {
    if (!isArray())
      return None;

    if (auto *Result =
            cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
      return Result;

    return None;
  }

  /// This might return None even if isArray() returns true,
  /// since there might not be an array size expression.
  /// If the result is not-None, it will never wrap a nullptr.
  Optional<const Expr *> getArraySize() const {
    if (!isArray())
      return None;

    if (auto *Result =
            cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
      return Result;

    return None;
  }

  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_PRValue, 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_PRValue, 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_PRValue, 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(QualType T, TypeSourceInfo *TSI,
                             SourceLocation LParenLoc, ArrayRef<Expr *> Args,
                             SourceLocation RParenLoc);

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

public:
  static CXXUnresolvedConstructExpr *Create(const ASTContext &Context,
                                            QualType T, TypeSourceInfo *TSI,
                                            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 getNumArgs() 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() + getNumArgs(); }
  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() + getNumArgs(); }
  const_arg_range arguments() const {
    return const_arg_range(arg_begin(), arg_end());
  }

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

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

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

  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY {
    if (!RParenLoc.isValid() && getNumArgs() > 0)
      return getArg(getNumArgs() - 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 + getNumArgs());
  }

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

/// 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_PRValue, 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_PRValue, 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 and a flag indicating if it was a reference
  /// parameter. For class NTTPs, we can't determine that based on the value
  /// category alone.
  llvm::PointerIntPair<NonTypeTemplateParmDecl*, 1, bool> ParamAndRef;

  /// The replacement expression.
  Stmt *Replacement;

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

public:
  SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
                               SourceLocation Loc,
                               NonTypeTemplateParmDecl *Param, bool RefParam,
                               Expr *Replacement)
      : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
        ParamAndRef(Param, RefParam), 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 ParamAndRef.getPointer();
  }

  bool isReferenceParameter() const { return ParamAndRef.getInt(); }

  /// Determine the substituted type of the template parameter.
  QualType getParameterType(const ASTContext &Ctx) const;

  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 isLValue(); }

  /// Determine whether this temporary object is usable in constant
  /// expressions, as specified in C++20 [expr.const]p4.
  bool isUsableInConstantExpressions(const ASTContext &Context) const;

  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;

  enum SubExpr { Callee, LHS, RHS, Count };

  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[SubExpr::Count];
  BinaryOperatorKind Opcode;

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

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

  UnresolvedLookupExpr *getCallee() const {
    return static_cast<UnresolvedLookupExpr *>(SubExprs[SubExpr::Callee]);
  }
  Expr *getLHS() const { return static_cast<Expr*>(SubExprs[SubExpr::LHS]); }
  Expr *getRHS() const { return static_cast<Expr*>(SubExprs[SubExpr::RHS]); }

  /// 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 getLParenLoc() const { return LParenLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  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 {
    if (LParenLoc.isValid())
      return LParenLoc;
    if (isLeftFold())
      return getEllipsisLoc();
    return getLHS()->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY {
    if (RParenLoc.isValid())
      return RParenLoc;
    if (isRightFold())
      return getEllipsisLoc();
    return getRHS()->getEndLoc();
  }

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

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

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

/// 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 { Operand, Common, Ready, Suspend, Resume, Count };

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

public:
  CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand,
                       Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume,
                       OpaqueValueExpr *OpaqueValue)
      : Expr(SC, Resume->getType(), Resume->getValueKind(),
             Resume->getObjectKind()),
        KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
    SubExprs[SubExpr::Operand] = Operand;
    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 *Operand, Expr *Common)
      : Expr(SC, Ty, VK_PRValue, OK_Ordinary), KeywordLoc(KeywordLoc) {
    assert(Common->isTypeDependent() && Ty->isDependentType() &&
           "wrong constructor for non-dependent co_await/co_yield expression");
    SubExprs[SubExpr::Operand] = Operand;
    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::Operand] = nullptr;
    SubExprs[SubExpr::Common] = nullptr;
    SubExprs[SubExpr::Ready] = nullptr;
    SubExprs[SubExpr::Suspend] = nullptr;
    SubExprs[SubExpr::Resume] = nullptr;
  }

  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]);
  }

  // The syntactic operand written in the code
  Expr *getOperand() const {
    return static_cast<Expr *>(SubExprs[SubExpr::Operand]);
  }

  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 + 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 *Common,
              Expr *Ready, Expr *Suspend, Expr *Resume,
              OpaqueValueExpr *OpaqueValue, bool IsImplicit = false)
      : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Common,
                             Ready, Suspend, Resume, OpaqueValue) {
    CoawaitBits.IsImplicit = IsImplicit;
  }

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

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

  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_PRValue, 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 *Common,
              Expr *Ready, Expr *Suspend, Expr *Resume,
              OpaqueValueExpr *OpaqueValue)
      : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Common,
                             Ready, Suspend, Resume, OpaqueValue) {}
  CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand,
              Expr *Common)
      : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand,
                             Common) {}
  CoyieldExpr(EmptyShell Empty)
      : CoroutineSuspendExpr(CoyieldExprClass, Empty) {}

  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 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, false,
                         DstType),
        KWLoc(KWLoc), RParenLoc(RParenLoc) {}
  BuiltinBitCastExpr(EmptyShell Empty)
      : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0, false) {}

  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
