//===--- Expr.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
//
//===----------------------------------------------------------------------===//
//
//  This file defines the Expr interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPR_H
#define LLVM_CLANG_AST_EXPR_H

#include "clang/AST/APValue.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"

namespace clang {
  class APValue;
  class ASTContext;
  class BlockDecl;
  class CXXBaseSpecifier;
  class CXXMemberCallExpr;
  class CXXOperatorCallExpr;
  class CastExpr;
  class Decl;
  class IdentifierInfo;
  class MaterializeTemporaryExpr;
  class NamedDecl;
  class ObjCPropertyRefExpr;
  class OpaqueValueExpr;
  class ParmVarDecl;
  class StringLiteral;
  class TargetInfo;
  class ValueDecl;

/// A simple array of base specifiers.
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;

/// An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
struct SubobjectAdjustment {
  enum {
    DerivedToBaseAdjustment,
    FieldAdjustment,
    MemberPointerAdjustment
  } Kind;

  struct DTB {
    const CastExpr *BasePath;
    const CXXRecordDecl *DerivedClass;
  };

  struct P {
    const MemberPointerType *MPT;
    Expr *RHS;
  };

  union {
    struct DTB DerivedToBase;
    FieldDecl *Field;
    struct P Ptr;
  };

  SubobjectAdjustment(const CastExpr *BasePath,
                      const CXXRecordDecl *DerivedClass)
    : Kind(DerivedToBaseAdjustment) {
    DerivedToBase.BasePath = BasePath;
    DerivedToBase.DerivedClass = DerivedClass;
  }

  SubobjectAdjustment(FieldDecl *Field)
    : Kind(FieldAdjustment) {
    this->Field = Field;
  }

  SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS)
    : Kind(MemberPointerAdjustment) {
    this->Ptr.MPT = MPT;
    this->Ptr.RHS = RHS;
  }
};

/// This represents one expression.  Note that Expr's are subclasses of Stmt.
/// This allows an expression to be transparently used any place a Stmt is
/// required.
class Expr : public ValueStmt {
  QualType TR;

public:
  Expr() = delete;
  Expr(const Expr&) = delete;
  Expr(Expr &&) = delete;
  Expr &operator=(const Expr&) = delete;
  Expr &operator=(Expr&&) = delete;

protected:
  Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK)
      : ValueStmt(SC) {
    ExprBits.Dependent = 0;
    ExprBits.ValueKind = VK;
    ExprBits.ObjectKind = OK;
    assert(ExprBits.ObjectKind == OK && "truncated kind");
    setType(T);
  }

  /// Construct an empty expression.
  explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { }

  /// Each concrete expr subclass is expected to compute its dependence and call
  /// this in the constructor.
  void setDependence(ExprDependence Deps) {
    ExprBits.Dependent = static_cast<unsigned>(Deps);
  }
  friend class ASTImporter; // Sets dependence dircetly.
  friend class ASTStmtReader; // Sets dependence dircetly.

public:
  QualType getType() const { return TR; }
  void setType(QualType t) {
    // In C++, the type of an expression is always adjusted so that it
    // will not have reference type (C++ [expr]p6). Use
    // QualType::getNonReferenceType() to retrieve the non-reference
    // type. Additionally, inspect Expr::isLvalue to determine whether
    // an expression that is adjusted in this manner should be
    // considered an lvalue.
    assert((t.isNull() || !t->isReferenceType()) &&
           "Expressions can't have reference type");

    TR = t;
  }

  ExprDependence getDependence() const {
    return static_cast<ExprDependence>(ExprBits.Dependent);
  }

  /// Determines whether the value of this expression depends on
  ///   - a template parameter (C++ [temp.dep.constexpr])
  ///   - or an error, whose resolution is unknown
  ///
  /// For example, the array bound of "Chars" in the following example is
  /// value-dependent.
  /// @code
  /// template<int Size, char (&Chars)[Size]> struct meta_string;
  /// @endcode
  bool isValueDependent() const {
    return static_cast<bool>(getDependence() & ExprDependence::Value);
  }

  /// Determines whether the type of this expression depends on
  ///   - a template paramter (C++ [temp.dep.expr], which means that its type
  ///     could change from one template instantiation to the next)
  ///   - or an error
  ///
  /// For example, the expressions "x" and "x + y" are type-dependent in
  /// the following code, but "y" is not type-dependent:
  /// @code
  /// template<typename T>
  /// void add(T x, int y) {
  ///   x + y;
  /// }
  /// @endcode
  bool isTypeDependent() const {
    return static_cast<bool>(getDependence() & ExprDependence::Type);
  }

  /// Whether this expression is instantiation-dependent, meaning that
  /// it depends in some way on
  ///    - a template parameter (even if neither its type nor (constant) value
  ///      can change due to the template instantiation)
  ///    - or an error
  ///
  /// In the following example, the expression \c sizeof(sizeof(T() + T())) is
  /// instantiation-dependent (since it involves a template parameter \c T), but
  /// is neither type- nor value-dependent, since the type of the inner
  /// \c sizeof is known (\c std::size_t) and therefore the size of the outer
  /// \c sizeof is known.
  ///
  /// \code
  /// template<typename T>
  /// void f(T x, T y) {
  ///   sizeof(sizeof(T() + T());
  /// }
  /// \endcode
  ///
  /// \code
  /// void func(int) {
  ///   func(); // the expression is instantiation-dependent, because it depends
  ///           // on an error.
  /// }
  /// \endcode
  bool isInstantiationDependent() const {
    return static_cast<bool>(getDependence() & ExprDependence::Instantiation);
  }

  /// Whether this expression contains an unexpanded parameter
  /// pack (for C++11 variadic templates).
  ///
  /// Given the following function template:
  ///
  /// \code
  /// template<typename F, typename ...Types>
  /// void forward(const F &f, Types &&...args) {
  ///   f(static_cast<Types&&>(args)...);
  /// }
  /// \endcode
  ///
  /// The expressions \c args and \c static_cast<Types&&>(args) both
  /// contain parameter packs.
  bool containsUnexpandedParameterPack() const {
    return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
  }

  /// Whether this expression contains subexpressions which had errors, e.g. a
  /// TypoExpr.
  bool containsErrors() const {
    return static_cast<bool>(getDependence() & ExprDependence::Error);
  }

  /// getExprLoc - Return the preferred location for the arrow when diagnosing
  /// a problem with a generic expression.
  SourceLocation getExprLoc() const LLVM_READONLY;

  /// Determine whether an lvalue-to-rvalue conversion should implicitly be
  /// applied to this expression if it appears as a discarded-value expression
  /// in C++11 onwards. This applies to certain forms of volatile glvalues.
  bool isReadIfDiscardedInCPlusPlus11() const;

  /// isUnusedResultAWarning - Return true if this immediate expression should
  /// be warned about if the result is unused.  If so, fill in expr, location,
  /// and ranges with expr to warn on and source locations/ranges appropriate
  /// for a warning.
  bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
                              SourceRange &R1, SourceRange &R2,
                              ASTContext &Ctx) const;

  /// isLValue - True if this expression is an "l-value" according to
  /// the rules of the current language.  C and C++ give somewhat
  /// different rules for this concept, but in general, the result of
  /// an l-value expression identifies a specific object whereas the
  /// result of an r-value expression is a value detached from any
  /// specific storage.
  ///
  /// C++11 divides the concept of "r-value" into pure r-values
  /// ("pr-values") and so-called expiring values ("x-values"), which
  /// identify specific objects that can be safely cannibalized for
  /// their resources.  This is an unfortunate abuse of terminology on
  /// the part of the C++ committee.  In Clang, when we say "r-value",
  /// we generally mean a pr-value.
  bool isLValue() const { return getValueKind() == VK_LValue; }
  bool isRValue() const { return getValueKind() == VK_RValue; }
  bool isXValue() const { return getValueKind() == VK_XValue; }
  bool isGLValue() const { return getValueKind() != VK_RValue; }

  enum LValueClassification {
    LV_Valid,
    LV_NotObjectType,
    LV_IncompleteVoidType,
    LV_DuplicateVectorComponents,
    LV_InvalidExpression,
    LV_InvalidMessageExpression,
    LV_MemberFunction,
    LV_SubObjCPropertySetting,
    LV_ClassTemporary,
    LV_ArrayTemporary
  };
  /// Reasons why an expression might not be an l-value.
  LValueClassification ClassifyLValue(ASTContext &Ctx) const;

  enum isModifiableLvalueResult {
    MLV_Valid,
    MLV_NotObjectType,
    MLV_IncompleteVoidType,
    MLV_DuplicateVectorComponents,
    MLV_InvalidExpression,
    MLV_LValueCast,           // Specialized form of MLV_InvalidExpression.
    MLV_IncompleteType,
    MLV_ConstQualified,
    MLV_ConstQualifiedField,
    MLV_ConstAddrSpace,
    MLV_ArrayType,
    MLV_NoSetterProperty,
    MLV_MemberFunction,
    MLV_SubObjCPropertySetting,
    MLV_InvalidMessageExpression,
    MLV_ClassTemporary,
    MLV_ArrayTemporary
  };
  /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
  /// does not have an incomplete type, does not have a const-qualified type,
  /// and if it is a structure or union, does not have any member (including,
  /// recursively, any member or element of all contained aggregates or unions)
  /// with a const-qualified type.
  ///
  /// \param Loc [in,out] - A source location which *may* be filled
  /// in with the location of the expression making this a
  /// non-modifiable lvalue, if specified.
  isModifiableLvalueResult
  isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;

  /// The return type of classify(). Represents the C++11 expression
  ///        taxonomy.
  class Classification {
  public:
    /// The various classification results. Most of these mean prvalue.
    enum Kinds {
      CL_LValue,
      CL_XValue,
      CL_Function, // Functions cannot be lvalues in C.
      CL_Void, // Void cannot be an lvalue in C.
      CL_AddressableVoid, // Void expression whose address can be taken in C.
      CL_DuplicateVectorComponents, // A vector shuffle with dupes.
      CL_MemberFunction, // An expression referring to a member function
      CL_SubObjCPropertySetting,
      CL_ClassTemporary, // A temporary of class type, or subobject thereof.
      CL_ArrayTemporary, // A temporary of array type.
      CL_ObjCMessageRValue, // ObjC message is an rvalue
      CL_PRValue // A prvalue for any other reason, of any other type
    };
    /// The results of modification testing.
    enum ModifiableType {
      CM_Untested, // testModifiable was false.
      CM_Modifiable,
      CM_RValue, // Not modifiable because it's an rvalue
      CM_Function, // Not modifiable because it's a function; C++ only
      CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
      CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
      CM_ConstQualified,
      CM_ConstQualifiedField,
      CM_ConstAddrSpace,
      CM_ArrayType,
      CM_IncompleteType
    };

  private:
    friend class Expr;

    unsigned short Kind;
    unsigned short Modifiable;

    explicit Classification(Kinds k, ModifiableType m)
      : Kind(k), Modifiable(m)
    {}

  public:
    Classification() {}

    Kinds getKind() const { return static_cast<Kinds>(Kind); }
    ModifiableType getModifiable() const {
      assert(Modifiable != CM_Untested && "Did not test for modifiability.");
      return static_cast<ModifiableType>(Modifiable);
    }
    bool isLValue() const { return Kind == CL_LValue; }
    bool isXValue() const { return Kind == CL_XValue; }
    bool isGLValue() const { return Kind <= CL_XValue; }
    bool isPRValue() const { return Kind >= CL_Function; }
    bool isRValue() const { return Kind >= CL_XValue; }
    bool isModifiable() const { return getModifiable() == CM_Modifiable; }

    /// Create a simple, modifiably lvalue
    static Classification makeSimpleLValue() {
      return Classification(CL_LValue, CM_Modifiable);
    }

  };
  /// Classify - Classify this expression according to the C++11
  ///        expression taxonomy.
  ///
  /// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the
  /// old lvalue vs rvalue. This function determines the type of expression this
  /// is. There are three expression types:
  /// - lvalues are classical lvalues as in C++03.
  /// - prvalues are equivalent to rvalues in C++03.
  /// - xvalues are expressions yielding unnamed rvalue references, e.g. a
  ///   function returning an rvalue reference.
  /// lvalues and xvalues are collectively referred to as glvalues, while
  /// prvalues and xvalues together form rvalues.
  Classification Classify(ASTContext &Ctx) const {
    return ClassifyImpl(Ctx, nullptr);
  }

  /// ClassifyModifiable - Classify this expression according to the
  ///        C++11 expression taxonomy, and see if it is valid on the left side
  ///        of an assignment.
  ///
  /// This function extends classify in that it also tests whether the
  /// expression is modifiable (C99 6.3.2.1p1).
  /// \param Loc A source location that might be filled with a relevant location
  ///            if the expression is not modifiable.
  Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{
    return ClassifyImpl(Ctx, &Loc);
  }

  /// Returns the set of floating point options that apply to this expression.
  /// Only meaningful for operations on floating point values.
  FPOptions getFPFeaturesInEffect(const LangOptions &LO) const;

  /// getValueKindForType - Given a formal return or parameter type,
  /// give its value kind.
  static ExprValueKind getValueKindForType(QualType T) {
    if (const ReferenceType *RT = T->getAs<ReferenceType>())
      return (isa<LValueReferenceType>(RT)
                ? VK_LValue
                : (RT->getPointeeType()->isFunctionType()
                     ? VK_LValue : VK_XValue));
    return VK_RValue;
  }

  /// getValueKind - The value kind that this expression produces.
  ExprValueKind getValueKind() const {
    return static_cast<ExprValueKind>(ExprBits.ValueKind);
  }

  /// getObjectKind - The object kind that this expression produces.
  /// Object kinds are meaningful only for expressions that yield an
  /// l-value or x-value.
  ExprObjectKind getObjectKind() const {
    return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
  }

  bool isOrdinaryOrBitFieldObject() const {
    ExprObjectKind OK = getObjectKind();
    return (OK == OK_Ordinary || OK == OK_BitField);
  }

  /// setValueKind - Set the value kind produced by this expression.
  void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }

  /// setObjectKind - Set the object kind produced by this expression.
  void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }

private:
  Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;

public:

  /// Returns true if this expression is a gl-value that
  /// potentially refers to a bit-field.
  ///
  /// In C++, whether a gl-value refers to a bitfield is essentially
  /// an aspect of the value-kind type system.
  bool refersToBitField() const { return getObjectKind() == OK_BitField; }

  /// If this expression refers to a bit-field, retrieve the
  /// declaration of that bit-field.
  ///
  /// Note that this returns a non-null pointer in subtly different
  /// places than refersToBitField returns true.  In particular, this can
  /// return a non-null pointer even for r-values loaded from
  /// bit-fields, but it will return null for a conditional bit-field.
  FieldDecl *getSourceBitField();

  const FieldDecl *getSourceBitField() const {
    return const_cast<Expr*>(this)->getSourceBitField();
  }

  Decl *getReferencedDeclOfCallee();
  const Decl *getReferencedDeclOfCallee() const {
    return const_cast<Expr*>(this)->getReferencedDeclOfCallee();
  }

  /// If this expression is an l-value for an Objective C
  /// property, find the underlying property reference expression.
  const ObjCPropertyRefExpr *getObjCProperty() const;

  /// Check if this expression is the ObjC 'self' implicit parameter.
  bool isObjCSelfExpr() const;

  /// Returns whether this expression refers to a vector element.
  bool refersToVectorElement() const;

  /// Returns whether this expression refers to a matrix element.
  bool refersToMatrixElement() const {
    return getObjectKind() == OK_MatrixComponent;
  }

  /// Returns whether this expression refers to a global register
  /// variable.
  bool refersToGlobalRegisterVar() const;

  /// Returns whether this expression has a placeholder type.
  bool hasPlaceholderType() const {
    return getType()->isPlaceholderType();
  }

  /// Returns whether this expression has a specific placeholder type.
  bool hasPlaceholderType(BuiltinType::Kind K) const {
    assert(BuiltinType::isPlaceholderTypeKind(K));
    if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType()))
      return BT->getKind() == K;
    return false;
  }

  /// isKnownToHaveBooleanValue - Return true if this is an integer expression
  /// that is known to return 0 or 1.  This happens for _Bool/bool expressions
  /// but also int expressions which are produced by things like comparisons in
  /// C.
  ///
  /// \param Semantic If true, only return true for expressions that are known
  /// to be semantically boolean, which might not be true even for expressions
  /// that are known to evaluate to 0/1. For instance, reading an unsigned
  /// bit-field with width '1' will evaluate to 0/1, but doesn't necessarily
  /// semantically correspond to a bool.
  bool isKnownToHaveBooleanValue(bool Semantic = true) const;

  /// isIntegerConstantExpr - Return the value if this expression is a valid
  /// integer constant expression.  If not a valid i-c-e, return None and fill
  /// in Loc (if specified) with the location of the invalid expression.
  ///
  /// Note: This does not perform the implicit conversions required by C++11
  /// [expr.const]p5.
  Optional<llvm::APSInt> getIntegerConstantExpr(const ASTContext &Ctx,
                                                SourceLocation *Loc = nullptr,
                                                bool isEvaluated = true) const;
  bool isIntegerConstantExpr(const ASTContext &Ctx,
                             SourceLocation *Loc = nullptr) const;

  /// isCXX98IntegralConstantExpr - Return true if this expression is an
  /// integral constant expression in C++98. Can only be used in C++.
  bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const;

  /// isCXX11ConstantExpr - Return true if this expression is a constant
  /// expression in C++11. Can only be used in C++.
  ///
  /// Note: This does not perform the implicit conversions required by C++11
  /// [expr.const]p5.
  bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr,
                           SourceLocation *Loc = nullptr) const;

  /// isPotentialConstantExpr - Return true if this function's definition
  /// might be usable in a constant expression in C++11, if it were marked
  /// constexpr. Return false if the function can never produce a constant
  /// expression, along with diagnostics describing why not.
  static bool isPotentialConstantExpr(const FunctionDecl *FD,
                                      SmallVectorImpl<
                                        PartialDiagnosticAt> &Diags);

  /// isPotentialConstantExprUnevaluted - Return true if this expression might
  /// be usable in a constant expression in C++11 in an unevaluated context, if
  /// it were in function FD marked constexpr. Return false if the function can
  /// never produce a constant expression, along with diagnostics describing
  /// why not.
  static bool isPotentialConstantExprUnevaluated(Expr *E,
                                                 const FunctionDecl *FD,
                                                 SmallVectorImpl<
                                                   PartialDiagnosticAt> &Diags);

  /// isConstantInitializer - Returns true if this expression can be emitted to
  /// IR as a constant, and thus can be used as a constant initializer in C.
  /// If this expression is not constant and Culprit is non-null,
  /// it is used to store the address of first non constant expr.
  bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
                             const Expr **Culprit = nullptr) const;

  /// EvalStatus is a struct with detailed info about an evaluation in progress.
  struct EvalStatus {
    /// Whether the evaluated expression has side effects.
    /// For example, (f() && 0) can be folded, but it still has side effects.
    bool HasSideEffects;

    /// Whether the evaluation hit undefined behavior.
    /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
    /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
    bool HasUndefinedBehavior;

    /// Diag - If this is non-null, it will be filled in with a stack of notes
    /// indicating why evaluation failed (or why it failed to produce a constant
    /// expression).
    /// If the expression is unfoldable, the notes will indicate why it's not
    /// foldable. If the expression is foldable, but not a constant expression,
    /// the notes will describes why it isn't a constant expression. If the
    /// expression *is* a constant expression, no notes will be produced.
    SmallVectorImpl<PartialDiagnosticAt> *Diag;

    EvalStatus()
        : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}

    // hasSideEffects - Return true if the evaluated expression has
    // side effects.
    bool hasSideEffects() const {
      return HasSideEffects;
    }
  };

  /// EvalResult is a struct with detailed info about an evaluated expression.
  struct EvalResult : EvalStatus {
    /// Val - This is the value the expression can be folded to.
    APValue Val;

    // isGlobalLValue - Return true if the evaluated lvalue expression
    // is global.
    bool isGlobalLValue() const;
  };

  /// EvaluateAsRValue - Return true if this is a constant which we can fold to
  /// an rvalue using any crazy technique (that has nothing to do with language
  /// standards) that we want to, even if the expression has side-effects. If
  /// this function returns true, it returns the folded constant in Result. If
  /// the expression is a glvalue, an lvalue-to-rvalue conversion will be
  /// applied.
  bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
                        bool InConstantContext = false) const;

  /// EvaluateAsBooleanCondition - Return true if this is a constant
  /// which we can fold and convert to a boolean condition using
  /// any crazy technique that we want to, even if the expression has
  /// side-effects.
  bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx,
                                  bool InConstantContext = false) const;

  enum SideEffectsKind {
    SE_NoSideEffects,          ///< Strictly evaluate the expression.
    SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not
                               ///< arbitrary unmodeled side effects.
    SE_AllowSideEffects        ///< Allow any unmodeled side effect.
  };

  /// EvaluateAsInt - Return true if this is a constant which we can fold and
  /// convert to an integer, using any crazy technique that we want to.
  bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
                     SideEffectsKind AllowSideEffects = SE_NoSideEffects,
                     bool InConstantContext = false) const;

  /// EvaluateAsFloat - Return true if this is a constant which we can fold and
  /// convert to a floating point value, using any crazy technique that we
  /// want to.
  bool EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx,
                       SideEffectsKind AllowSideEffects = SE_NoSideEffects,
                       bool InConstantContext = false) const;

  /// EvaluateAsFloat - Return true if this is a constant which we can fold and
  /// convert to a fixed point value.
  bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx,
                            SideEffectsKind AllowSideEffects = SE_NoSideEffects,
                            bool InConstantContext = false) const;

  /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
  /// constant folded without side-effects, but discard the result.
  bool isEvaluatable(const ASTContext &Ctx,
                     SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;

  /// HasSideEffects - This routine returns true for all those expressions
  /// which have any effect other than producing a value. Example is a function
  /// call, volatile variable read, or throwing an exception. If
  /// IncludePossibleEffects is false, this call treats certain expressions with
  /// potential side effects (such as function call-like expressions,
  /// instantiation-dependent expressions, or invocations from a macro) as not
  /// having side effects.
  bool HasSideEffects(const ASTContext &Ctx,
                      bool IncludePossibleEffects = true) const;

  /// Determine whether this expression involves a call to any function
  /// that is not trivial.
  bool hasNonTrivialCall(const ASTContext &Ctx) const;

  /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
  /// integer. This must be called on an expression that constant folds to an
  /// integer.
  llvm::APSInt EvaluateKnownConstInt(
      const ASTContext &Ctx,
      SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;

  llvm::APSInt EvaluateKnownConstIntCheckOverflow(
      const ASTContext &Ctx,
      SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;

  void EvaluateForOverflow(const ASTContext &Ctx) const;

  /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
  /// lvalue with link time known address, with no side-effects.
  bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx,
                        bool InConstantContext = false) const;

  /// EvaluateAsInitializer - Evaluate an expression as if it were the
  /// initializer of the given declaration. Returns true if the initializer
  /// can be folded to a constant, and produces any relevant notes. In C++11,
  /// notes will be produced if the expression is not a constant expression.
  bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx,
                             const VarDecl *VD,
                             SmallVectorImpl<PartialDiagnosticAt> &Notes,
                             bool IsConstantInitializer) const;

  /// EvaluateWithSubstitution - Evaluate an expression as if from the context
  /// of a call to the given function with the given arguments, inside an
  /// unevaluated context. Returns true if the expression could be folded to a
  /// constant.
  bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
                                const FunctionDecl *Callee,
                                ArrayRef<const Expr*> Args,
                                const Expr *This = nullptr) const;

  enum class ConstantExprKind {
    /// An integer constant expression (an array bound, enumerator, case value,
    /// bit-field width, or similar) or similar.
    Normal,
    /// A non-class template argument. Such a value is only used for mangling,
    /// not for code generation, so can refer to dllimported functions.
    NonClassTemplateArgument,
    /// A class template argument. Such a value is used for code generation.
    ClassTemplateArgument,
    /// An immediate invocation. The destruction of the end result of this
    /// evaluation is not part of the evaluation, but all other temporaries
    /// are destroyed.
    ImmediateInvocation,
  };

  /// Evaluate an expression that is required to be a constant expression. Does
  /// not check the syntactic constraints for C and C++98 constant expressions.
  bool EvaluateAsConstantExpr(
      EvalResult &Result, const ASTContext &Ctx,
      ConstantExprKind Kind = ConstantExprKind::Normal) const;

  /// If the current Expr is a pointer, this will try to statically
  /// determine the number of bytes available where the pointer is pointing.
  /// Returns true if all of the above holds and we were able to figure out the
  /// size, false otherwise.
  ///
  /// \param Type - How to evaluate the size of the Expr, as defined by the
  /// "type" parameter of __builtin_object_size
  bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
                             unsigned Type) const;

  /// Enumeration used to describe the kind of Null pointer constant
  /// returned from \c isNullPointerConstant().
  enum NullPointerConstantKind {
    /// Expression is not a Null pointer constant.
    NPCK_NotNull = 0,

    /// Expression is a Null pointer constant built from a zero integer
    /// expression that is not a simple, possibly parenthesized, zero literal.
    /// C++ Core Issue 903 will classify these expressions as "not pointers"
    /// once it is adopted.
    /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
    NPCK_ZeroExpression,

    /// Expression is a Null pointer constant built from a literal zero.
    NPCK_ZeroLiteral,

    /// Expression is a C++11 nullptr.
    NPCK_CXX11_nullptr,

    /// Expression is a GNU-style __null constant.
    NPCK_GNUNull
  };

  /// Enumeration used to describe how \c isNullPointerConstant()
  /// should cope with value-dependent expressions.
  enum NullPointerConstantValueDependence {
    /// Specifies that the expression should never be value-dependent.
    NPC_NeverValueDependent = 0,

    /// Specifies that a value-dependent expression of integral or
    /// dependent type should be considered a null pointer constant.
    NPC_ValueDependentIsNull,

    /// Specifies that a value-dependent expression should be considered
    /// to never be a null pointer constant.
    NPC_ValueDependentIsNotNull
  };

  /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
  /// a Null pointer constant. The return value can further distinguish the
  /// kind of NULL pointer constant that was detected.
  NullPointerConstantKind isNullPointerConstant(
      ASTContext &Ctx,
      NullPointerConstantValueDependence NPC) const;

  /// isOBJCGCCandidate - Return true if this expression may be used in a read/
  /// write barrier.
  bool isOBJCGCCandidate(ASTContext &Ctx) const;

  /// Returns true if this expression is a bound member function.
  bool isBoundMemberFunction(ASTContext &Ctx) const;

  /// Given an expression of bound-member type, find the type
  /// of the member.  Returns null if this is an *overloaded* bound
  /// member expression.
  static QualType findBoundMemberType(const Expr *expr);

  /// Skip past any invisble AST nodes which might surround this
  /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes,
  /// but also injected CXXMemberExpr and CXXConstructExpr which represent
  /// implicit conversions.
  Expr *IgnoreUnlessSpelledInSource();
  const Expr *IgnoreUnlessSpelledInSource() const {
    return const_cast<Expr *>(this)->IgnoreUnlessSpelledInSource();
  }

  /// Skip past any implicit casts which might surround this expression until
  /// reaching a fixed point. Skips:
  /// * ImplicitCastExpr
  /// * FullExpr
  Expr *IgnoreImpCasts() LLVM_READONLY;
  const Expr *IgnoreImpCasts() const {
    return const_cast<Expr *>(this)->IgnoreImpCasts();
  }

  /// Skip past any casts which might surround this expression until reaching
  /// a fixed point. Skips:
  /// * CastExpr
  /// * FullExpr
  /// * MaterializeTemporaryExpr
  /// * SubstNonTypeTemplateParmExpr
  Expr *IgnoreCasts() LLVM_READONLY;
  const Expr *IgnoreCasts() const {
    return const_cast<Expr *>(this)->IgnoreCasts();
  }

  /// Skip past any implicit AST nodes which might surround this expression
  /// until reaching a fixed point. Skips:
  /// * What IgnoreImpCasts() skips
  /// * MaterializeTemporaryExpr
  /// * CXXBindTemporaryExpr
  Expr *IgnoreImplicit() LLVM_READONLY;
  const Expr *IgnoreImplicit() const {
    return const_cast<Expr *>(this)->IgnoreImplicit();
  }

  /// Skip past any implicit AST nodes which might surround this expression
  /// until reaching a fixed point. Same as IgnoreImplicit, except that it
  /// also skips over implicit calls to constructors and conversion functions.
  ///
  /// FIXME: Should IgnoreImplicit do this?
  Expr *IgnoreImplicitAsWritten() LLVM_READONLY;
  const Expr *IgnoreImplicitAsWritten() const {
    return const_cast<Expr *>(this)->IgnoreImplicitAsWritten();
  }

  /// Skip past any parentheses which might surround this expression until
  /// reaching a fixed point. Skips:
  /// * ParenExpr
  /// * UnaryOperator if `UO_Extension`
  /// * GenericSelectionExpr if `!isResultDependent()`
  /// * ChooseExpr if `!isConditionDependent()`
  /// * ConstantExpr
  Expr *IgnoreParens() LLVM_READONLY;
  const Expr *IgnoreParens() const {
    return const_cast<Expr *>(this)->IgnoreParens();
  }

  /// Skip past any parentheses and implicit casts which might surround this
  /// expression until reaching a fixed point.
  /// FIXME: IgnoreParenImpCasts really ought to be equivalent to
  /// IgnoreParens() + IgnoreImpCasts() until reaching a fixed point. However
  /// this is currently not the case. Instead IgnoreParenImpCasts() skips:
  /// * What IgnoreParens() skips
  /// * What IgnoreImpCasts() skips
  /// * MaterializeTemporaryExpr
  /// * SubstNonTypeTemplateParmExpr
  Expr *IgnoreParenImpCasts() LLVM_READONLY;
  const Expr *IgnoreParenImpCasts() const {
    return const_cast<Expr *>(this)->IgnoreParenImpCasts();
  }

  /// Skip past any parentheses and casts which might surround this expression
  /// until reaching a fixed point. Skips:
  /// * What IgnoreParens() skips
  /// * What IgnoreCasts() skips
  Expr *IgnoreParenCasts() LLVM_READONLY;
  const Expr *IgnoreParenCasts() const {
    return const_cast<Expr *>(this)->IgnoreParenCasts();
  }

  /// Skip conversion operators. If this Expr is a call to a conversion
  /// operator, return the argument.
  Expr *IgnoreConversionOperatorSingleStep() LLVM_READONLY;
  const Expr *IgnoreConversionOperatorSingleStep() const {
    return const_cast<Expr *>(this)->IgnoreConversionOperatorSingleStep();
  }

  /// Skip past any parentheses and lvalue casts which might surround this
  /// expression until reaching a fixed point. Skips:
  /// * What IgnoreParens() skips
  /// * What IgnoreCasts() skips, except that only lvalue-to-rvalue
  ///   casts are skipped
  /// FIXME: This is intended purely as a temporary workaround for code
  /// that hasn't yet been rewritten to do the right thing about those
  /// casts, and may disappear along with the last internal use.
  Expr *IgnoreParenLValueCasts() LLVM_READONLY;
  const Expr *IgnoreParenLValueCasts() const {
    return const_cast<Expr *>(this)->IgnoreParenLValueCasts();
  }

  /// Skip past any parenthese and casts which do not change the value
  /// (including ptr->int casts of the same size) until reaching a fixed point.
  /// Skips:
  /// * What IgnoreParens() skips
  /// * CastExpr which do not change the value
  /// * SubstNonTypeTemplateParmExpr
  Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY;
  const Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) const {
    return const_cast<Expr *>(this)->IgnoreParenNoopCasts(Ctx);
  }

  /// Skip past any parentheses and derived-to-base casts until reaching a
  /// fixed point. Skips:
  /// * What IgnoreParens() skips
  /// * CastExpr which represent a derived-to-base cast (CK_DerivedToBase,
  ///   CK_UncheckedDerivedToBase and CK_NoOp)
  Expr *IgnoreParenBaseCasts() LLVM_READONLY;
  const Expr *IgnoreParenBaseCasts() const {
    return const_cast<Expr *>(this)->IgnoreParenBaseCasts();
  }

  /// Determine whether this expression is a default function argument.
  ///
  /// Default arguments are implicitly generated in the abstract syntax tree
  /// by semantic analysis for function calls, object constructions, etc. in
  /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes;
  /// this routine also looks through any implicit casts to determine whether
  /// the expression is a default argument.
  bool isDefaultArgument() const;

  /// Determine whether the result of this expression is a
  /// temporary object of the given class type.
  bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;

  /// Whether this expression is an implicit reference to 'this' in C++.
  bool isImplicitCXXThis() const;

  static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);

  /// For an expression of class type or pointer to class type,
  /// return the most derived class decl the expression is known to refer to.
  ///
  /// If this expression is a cast, this method looks through it to find the
  /// most derived decl that can be inferred from the expression.
  /// This is valid because derived-to-base conversions have undefined
  /// behavior if the object isn't dynamically of the derived type.
  const CXXRecordDecl *getBestDynamicClassType() const;

  /// Get the inner expression that determines the best dynamic class.
  /// If this is a prvalue, we guarantee that it is of the most-derived type
  /// for the object itself.
  const Expr *getBestDynamicClassTypeExpr() const;

  /// Walk outwards from an expression we want to bind a reference to and
  /// find the expression whose lifetime needs to be extended. Record
  /// the LHSs of comma expressions and adjustments needed along the path.
  const Expr *skipRValueSubobjectAdjustments(
      SmallVectorImpl<const Expr *> &CommaLHS,
      SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
  const Expr *skipRValueSubobjectAdjustments() const {
    SmallVector<const Expr *, 8> CommaLHSs;
    SmallVector<SubobjectAdjustment, 8> Adjustments;
    return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
  }

  /// Checks that the two Expr's will refer to the same value as a comparison
  /// operand.  The caller must ensure that the values referenced by the Expr's
  /// are not modified between E1 and E2 or the result my be invalid.
  static bool isSameComparisonOperand(const Expr* E1, const Expr* E2);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() >= firstExprConstant &&
           T->getStmtClass() <= lastExprConstant;
  }
};
// PointerLikeTypeTraits is specialized so it can be used with a forward-decl of
// Expr. Verify that we got it right.
static_assert(llvm::PointerLikeTypeTraits<Expr *>::NumLowBitsAvailable <=
                  llvm::detail::ConstantLog2<alignof(Expr)>::value,
              "PointerLikeTypeTraits<Expr*> assumes too much alignment.");

using ConstantExprKind = Expr::ConstantExprKind;

//===----------------------------------------------------------------------===//
// Wrapper Expressions.
//===----------------------------------------------------------------------===//

/// FullExpr - Represents a "full-expression" node.
class FullExpr : public Expr {
protected:
 Stmt *SubExpr;

 FullExpr(StmtClass SC, Expr *subexpr)
     : Expr(SC, subexpr->getType(), subexpr->getValueKind(),
            subexpr->getObjectKind()),
       SubExpr(subexpr) {
   setDependence(computeDependence(this));
 }
  FullExpr(StmtClass SC, EmptyShell Empty)
    : Expr(SC, Empty) {}
public:
  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
  Expr *getSubExpr() { return cast<Expr>(SubExpr); }

  /// As with any mutator of the AST, be very careful when modifying an
  /// existing AST to preserve its invariants.
  void setSubExpr(Expr *E) { SubExpr = E; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() >= firstFullExprConstant &&
           T->getStmtClass() <= lastFullExprConstant;
  }
};

/// ConstantExpr - An expression that occurs in a constant context and
/// optionally the result of evaluating the expression.
class ConstantExpr final
    : public FullExpr,
      private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t> {
  static_assert(std::is_same<uint64_t, llvm::APInt::WordType>::value,
                "ConstantExpr assumes that llvm::APInt::WordType is uint64_t "
                "for tail-allocated storage");
  friend TrailingObjects;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

public:
  /// Describes the kind of result that can be tail-allocated.
  enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue };

private:
  size_t numTrailingObjects(OverloadToken<APValue>) const {
    return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue;
  }
  size_t numTrailingObjects(OverloadToken<uint64_t>) const {
    return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64;
  }

  uint64_t &Int64Result() {
    assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 &&
           "invalid accessor");
    return *getTrailingObjects<uint64_t>();
  }
  const uint64_t &Int64Result() const {
    return const_cast<ConstantExpr *>(this)->Int64Result();
  }
  APValue &APValueResult() {
    assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue &&
           "invalid accessor");
    return *getTrailingObjects<APValue>();
  }
  APValue &APValueResult() const {
    return const_cast<ConstantExpr *>(this)->APValueResult();
  }

  ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind,
               bool IsImmediateInvocation);
  ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind);

public:
  static ConstantExpr *Create(const ASTContext &Context, Expr *E,
                              const APValue &Result);
  static ConstantExpr *Create(const ASTContext &Context, Expr *E,
                              ResultStorageKind Storage = RSK_None,
                              bool IsImmediateInvocation = false);
  static ConstantExpr *CreateEmpty(const ASTContext &Context,
                                   ResultStorageKind StorageKind);

  static ResultStorageKind getStorageKind(const APValue &Value);
  static ResultStorageKind getStorageKind(const Type *T,
                                          const ASTContext &Context);

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

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

  void SetResult(APValue Value, const ASTContext &Context) {
    MoveIntoResult(Value, Context);
  }
  void MoveIntoResult(APValue &Value, const ASTContext &Context);

  APValue::ValueKind getResultAPValueKind() const {
    return static_cast<APValue::ValueKind>(ConstantExprBits.APValueKind);
  }
  ResultStorageKind getResultStorageKind() const {
    return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind);
  }
  bool isImmediateInvocation() const {
    return ConstantExprBits.IsImmediateInvocation;
  }
  bool hasAPValueResult() const {
    return ConstantExprBits.APValueKind != APValue::None;
  }
  APValue getAPValueResult() const;
  APValue &getResultAsAPValue() const { return APValueResult(); }
  llvm::APSInt getResultAsAPSInt() const;
  // Iterators
  child_range children() { return child_range(&SubExpr, &SubExpr+1); }
  const_child_range children() const {
    return const_child_range(&SubExpr, &SubExpr + 1);
  }
};

//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//

/// OpaqueValueExpr - An expression referring to an opaque object of a
/// fixed type and value class.  These don't correspond to concrete
/// syntax; instead they're used to express operations (usually copy
/// operations) on values whose source is generally obvious from
/// context.
class OpaqueValueExpr : public Expr {
  friend class ASTStmtReader;
  Expr *SourceExpr;

public:
  OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
                  ExprObjectKind OK = OK_Ordinary, Expr *SourceExpr = nullptr)
      : Expr(OpaqueValueExprClass, T, VK, OK), SourceExpr(SourceExpr) {
    setIsUnique(false);
    OpaqueValueExprBits.Loc = Loc;
    setDependence(computeDependence(this));
  }

  /// Given an expression which invokes a copy constructor --- i.e.  a
  /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
  /// find the OpaqueValueExpr that's the source of the construction.
  static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);

  explicit OpaqueValueExpr(EmptyShell Empty)
    : Expr(OpaqueValueExprClass, Empty) {}

  /// Retrieve the location of this expression.
  SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return SourceExpr ? SourceExpr->getBeginLoc() : getLocation();
  }
  SourceLocation getEndLoc() const LLVM_READONLY {
    return SourceExpr ? SourceExpr->getEndLoc() : getLocation();
  }
  SourceLocation getExprLoc() const LLVM_READONLY {
    return SourceExpr ? SourceExpr->getExprLoc() : getLocation();
  }

  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 source expression of an opaque value expression is the
  /// expression which originally generated the value.  This is
  /// provided as a convenience for analyses that don't wish to
  /// precisely model the execution behavior of the program.
  ///
  /// The source expression is typically set when building the
  /// expression which binds the opaque value expression in the first
  /// place.
  Expr *getSourceExpr() const { return SourceExpr; }

  void setIsUnique(bool V) {
    assert((!V || SourceExpr) &&
           "unique OVEs are expected to have source expressions");
    OpaqueValueExprBits.IsUnique = V;
  }

  bool isUnique() const { return OpaqueValueExprBits.IsUnique; }

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

/// A reference to a declared variable, function, enum, etc.
/// [C99 6.5.1p2]
///
/// This encodes all the information about how a declaration is referenced
/// within an expression.
///
/// There are several optional constructs attached to DeclRefExprs only when
/// they apply in order to conserve memory. These are laid out past the end of
/// the object, and flags in the DeclRefExprBitfield track whether they exist:
///
///   DeclRefExprBits.HasQualifier:
///       Specifies when this declaration reference expression has a C++
///       nested-name-specifier.
///   DeclRefExprBits.HasFoundDecl:
///       Specifies when this declaration reference expression has a record of
///       a NamedDecl (different from the referenced ValueDecl) which was found
///       during name lookup and/or overload resolution.
///   DeclRefExprBits.HasTemplateKWAndArgsInfo:
///       Specifies when this declaration reference expression has an explicit
///       C++ template keyword and/or template argument list.
///   DeclRefExprBits.RefersToEnclosingVariableOrCapture
///       Specifies when this declaration reference expression (validly)
///       refers to an enclosed local or a captured variable.
class DeclRefExpr final
    : public Expr,
      private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
                                    NamedDecl *, ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The declaration that we are referencing.
  ValueDecl *D;

  /// Provides source/type location info for the declaration name
  /// embedded in D.
  DeclarationNameLoc DNLoc;

  size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
    return hasQualifier();
  }

  size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
    return hasFoundDecl();
  }

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

  /// Test whether there is a distinct FoundDecl attached to the end of
  /// this DRE.
  bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }

  DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
              SourceLocation TemplateKWLoc, ValueDecl *D,
              bool RefersToEnlosingVariableOrCapture,
              const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
              const TemplateArgumentListInfo *TemplateArgs, QualType T,
              ExprValueKind VK, NonOdrUseReason NOUR);

  /// Construct an empty declaration reference expression.
  explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {}

public:
  DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
              bool RefersToEnclosingVariableOrCapture, QualType T,
              ExprValueKind VK, SourceLocation L,
              const DeclarationNameLoc &LocInfo = DeclarationNameLoc(),
              NonOdrUseReason NOUR = NOUR_None);

  static DeclRefExpr *
  Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
         SourceLocation TemplateKWLoc, ValueDecl *D,
         bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
         QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
         const TemplateArgumentListInfo *TemplateArgs = nullptr,
         NonOdrUseReason NOUR = NOUR_None);

  static DeclRefExpr *
  Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
         SourceLocation TemplateKWLoc, ValueDecl *D,
         bool RefersToEnclosingVariableOrCapture,
         const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
         NamedDecl *FoundD = nullptr,
         const TemplateArgumentListInfo *TemplateArgs = nullptr,
         NonOdrUseReason NOUR = NOUR_None);

  /// Construct an empty declaration reference expression.
  static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
                                  bool HasFoundDecl,
                                  bool HasTemplateKWAndArgsInfo,
                                  unsigned NumTemplateArgs);

  ValueDecl *getDecl() { return D; }
  const ValueDecl *getDecl() const { return D; }
  void setDecl(ValueDecl *NewD);

  DeclarationNameInfo getNameInfo() const {
    return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc);
  }

  SourceLocation getLocation() const { return DeclRefExprBits.Loc; }
  void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; }
  SourceLocation getBeginLoc() const LLVM_READONLY;
  SourceLocation getEndLoc() const LLVM_READONLY;

  /// Determine whether this declaration reference was preceded by a
  /// C++ nested-name-specifier, e.g., \c N::foo.
  bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }

  /// If the name was qualified, retrieves the nested-name-specifier
  /// that precedes the name, with source-location information.
  NestedNameSpecifierLoc getQualifierLoc() const {
    if (!hasQualifier())
      return NestedNameSpecifierLoc();
    return *getTrailingObjects<NestedNameSpecifierLoc>();
  }

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

  /// Get the NamedDecl through which this reference occurred.
  ///
  /// This Decl may be different from the ValueDecl actually referred to in the
  /// presence of using declarations, etc. It always returns non-NULL, and may
  /// simple return the ValueDecl when appropriate.

  NamedDecl *getFoundDecl() {
    return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
  }

  /// Get the NamedDecl through which this reference occurred.
  /// See non-const variant.
  const NamedDecl *getFoundDecl() const {
    return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
  }

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

  /// 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 in this declaration reference
  /// was preceded by the template keyword.
  bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

  /// Determines whether this declaration reference was followed by an
  /// explicit template argument list.
  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()};
  }

  /// Returns true if this expression refers to a function that
  /// was resolved from an overloaded set having size greater than 1.
  bool hadMultipleCandidates() const {
    return DeclRefExprBits.HadMultipleCandidates;
  }
  /// Sets the flag telling whether this expression refers to
  /// a function that was resolved from an overloaded set having size
  /// greater than 1.
  void setHadMultipleCandidates(bool V = true) {
    DeclRefExprBits.HadMultipleCandidates = V;
  }

  /// Is this expression a non-odr-use reference, and if so, why?
  NonOdrUseReason isNonOdrUse() const {
    return static_cast<NonOdrUseReason>(DeclRefExprBits.NonOdrUseReason);
  }

  /// Does this DeclRefExpr refer to an enclosing local or a captured
  /// variable?
  bool refersToEnclosingVariableOrCapture() const {
    return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
  }

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

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

/// Used by IntegerLiteral/FloatingLiteral to store the numeric without
/// leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers.  Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
  union {
    uint64_t VAL;    ///< Used to store the <= 64 bits integer value.
    uint64_t *pVal;  ///< Used to store the >64 bits integer value.
  };
  unsigned BitWidth;

  bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }

  APNumericStorage(const APNumericStorage &) = delete;
  void operator=(const APNumericStorage &) = delete;

protected:
  APNumericStorage() : VAL(0), BitWidth(0) { }

  llvm::APInt getIntValue() const {
    unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
    if (NumWords > 1)
      return llvm::APInt(BitWidth, NumWords, pVal);
    else
      return llvm::APInt(BitWidth, VAL);
  }
  void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};

class APIntStorage : private APNumericStorage {
public:
  llvm::APInt getValue() const { return getIntValue(); }
  void setValue(const ASTContext &C, const llvm::APInt &Val) {
    setIntValue(C, Val);
  }
};

class APFloatStorage : private APNumericStorage {
public:
  llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
    return llvm::APFloat(Semantics, getIntValue());
  }
  void setValue(const ASTContext &C, const llvm::APFloat &Val) {
    setIntValue(C, Val.bitcastToAPInt());
  }
};

class IntegerLiteral : public Expr, public APIntStorage {
  SourceLocation Loc;

  /// Construct an empty integer literal.
  explicit IntegerLiteral(EmptyShell Empty)
    : Expr(IntegerLiteralClass, Empty) { }

public:
  // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
  // or UnsignedLongLongTy
  IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
                 SourceLocation l);

  /// Returns a new integer literal with value 'V' and type 'type'.
  /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
  /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
  /// \param V - the value that the returned integer literal contains.
  static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
                                QualType type, SourceLocation l);
  /// Returns a new empty integer literal.
  static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);

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

  /// Retrieve the location of the literal.
  SourceLocation getLocation() const { return Loc; }

  void setLocation(SourceLocation Location) { Loc = Location; }

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

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

class FixedPointLiteral : public Expr, public APIntStorage {
  SourceLocation Loc;
  unsigned Scale;

  /// \brief Construct an empty fixed-point literal.
  explicit FixedPointLiteral(EmptyShell Empty)
      : Expr(FixedPointLiteralClass, Empty) {}

 public:
  FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
                    SourceLocation l, unsigned Scale);

  // Store the int as is without any bit shifting.
  static FixedPointLiteral *CreateFromRawInt(const ASTContext &C,
                                             const llvm::APInt &V,
                                             QualType type, SourceLocation l,
                                             unsigned Scale);

  /// Returns an empty fixed-point literal.
  static FixedPointLiteral *Create(const ASTContext &C, EmptyShell Empty);

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

  /// \brief Retrieve the location of the literal.
  SourceLocation getLocation() const { return Loc; }

  void setLocation(SourceLocation Location) { Loc = Location; }

  unsigned getScale() const { return Scale; }
  void setScale(unsigned S) { Scale = S; }

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

  std::string getValueAsString(unsigned Radix) const;

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

class CharacterLiteral : public Expr {
public:
  enum CharacterKind {
    Ascii,
    Wide,
    UTF8,
    UTF16,
    UTF32
  };

private:
  unsigned Value;
  SourceLocation Loc;
public:
  // type should be IntTy
  CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
                   SourceLocation l)
      : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary), Value(value),
        Loc(l) {
    CharacterLiteralBits.Kind = kind;
    setDependence(ExprDependence::None);
  }

  /// Construct an empty character literal.
  CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }

  SourceLocation getLocation() const { return Loc; }
  CharacterKind getKind() const {
    return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
  }

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

  unsigned getValue() const { return Value; }

  void setLocation(SourceLocation Location) { Loc = Location; }
  void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
  void setValue(unsigned Val) { Value = Val; }

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

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

class FloatingLiteral : public Expr, private APFloatStorage {
  SourceLocation Loc;

  FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
                  QualType Type, SourceLocation L);

  /// Construct an empty floating-point literal.
  explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);

public:
  static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V,
                                 bool isexact, QualType Type, SourceLocation L);
  static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);

  llvm::APFloat getValue() const {
    return APFloatStorage::getValue(getSemantics());
  }
  void setValue(const ASTContext &C, const llvm::APFloat &Val) {
    assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
    APFloatStorage::setValue(C, Val);
  }

  /// Get a raw enumeration value representing the floating-point semantics of
  /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
  llvm::APFloatBase::Semantics getRawSemantics() const {
    return static_cast<llvm::APFloatBase::Semantics>(
        FloatingLiteralBits.Semantics);
  }

  /// Set the raw enumeration value representing the floating-point semantics of
  /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
  void setRawSemantics(llvm::APFloatBase::Semantics Sem) {
    FloatingLiteralBits.Semantics = Sem;
  }

  /// Return the APFloat semantics this literal uses.
  const llvm::fltSemantics &getSemantics() const {
    return llvm::APFloatBase::EnumToSemantics(
        static_cast<llvm::APFloatBase::Semantics>(
            FloatingLiteralBits.Semantics));
  }

  /// Set the APFloat semantics this literal uses.
  void setSemantics(const llvm::fltSemantics &Sem) {
    FloatingLiteralBits.Semantics = llvm::APFloatBase::SemanticsToEnum(Sem);
  }

  bool isExact() const { return FloatingLiteralBits.IsExact; }
  void setExact(bool E) { FloatingLiteralBits.IsExact = E; }

  /// getValueAsApproximateDouble - This returns the value as an inaccurate
  /// double.  Note that this may cause loss of precision, but is useful for
  /// debugging dumps, etc.
  double getValueAsApproximateDouble() const;

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

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

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

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

/// ImaginaryLiteral - We support imaginary integer and floating point literals,
/// like "1.0i".  We represent these as a wrapper around FloatingLiteral and
/// IntegerLiteral classes.  Instances of this class always have a Complex type
/// whose element type matches the subexpression.
///
class ImaginaryLiteral : public Expr {
  Stmt *Val;
public:
  ImaginaryLiteral(Expr *val, QualType Ty)
      : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary), Val(val) {
    setDependence(ExprDependence::None);
  }

  /// Build an empty imaginary literal.
  explicit ImaginaryLiteral(EmptyShell Empty)
    : Expr(ImaginaryLiteralClass, Empty) { }

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

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

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

  // Iterators
  child_range children() { return child_range(&Val, &Val+1); }
  const_child_range children() const {
    return const_child_range(&Val, &Val + 1);
  }
};

/// StringLiteral - This represents a string literal expression, e.g. "foo"
/// or L"bar" (wide strings). The actual string data can be obtained with
/// getBytes() and is NOT null-terminated. The length of the string data is
/// determined by calling getByteLength().
///
/// The C type for a string is always a ConstantArrayType. In C++, the char
/// type is const qualified, in C it is not.
///
/// Note that strings in C can be formed by concatenation of multiple string
/// literal pptokens in translation phase #6. This keeps track of the locations
/// of each of these pieces.
///
/// Strings in C can also be truncated and extended by assigning into arrays,
/// e.g. with constructs like:
///   char X[2] = "foobar";
/// In this case, getByteLength() will return 6, but the string literal will
/// have type "char[2]".
class StringLiteral final
    : public Expr,
      private llvm::TrailingObjects<StringLiteral, unsigned, SourceLocation,
                                    char> {
  friend class ASTStmtReader;
  friend TrailingObjects;

  /// StringLiteral is followed by several trailing objects. They are in order:
  ///
  /// * A single unsigned storing the length in characters of this string. The
  ///   length in bytes is this length times the width of a single character.
  ///   Always present and stored as a trailing objects because storing it in
  ///   StringLiteral would increase the size of StringLiteral by sizeof(void *)
  ///   due to alignment requirements. If you add some data to StringLiteral,
  ///   consider moving it inside StringLiteral.
  ///
  /// * An array of getNumConcatenated() SourceLocation, one for each of the
  ///   token this string is made of.
  ///
  /// * An array of getByteLength() char used to store the string data.

public:
  enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 };

private:
  unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; }
  unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
    return getNumConcatenated();
  }

  unsigned numTrailingObjects(OverloadToken<char>) const {
    return getByteLength();
  }

  char *getStrDataAsChar() { return getTrailingObjects<char>(); }
  const char *getStrDataAsChar() const { return getTrailingObjects<char>(); }

  const uint16_t *getStrDataAsUInt16() const {
    return reinterpret_cast<const uint16_t *>(getTrailingObjects<char>());
  }

  const uint32_t *getStrDataAsUInt32() const {
    return reinterpret_cast<const uint32_t *>(getTrailingObjects<char>());
  }

  /// Build a string literal.
  StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind,
                bool Pascal, QualType Ty, const SourceLocation *Loc,
                unsigned NumConcatenated);

  /// Build an empty string literal.
  StringLiteral(EmptyShell Empty, unsigned NumConcatenated, unsigned Length,
                unsigned CharByteWidth);

  /// Map a target and string kind to the appropriate character width.
  static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK);

  /// Set one of the string literal token.
  void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
    assert(TokNum < getNumConcatenated() && "Invalid tok number");
    getTrailingObjects<SourceLocation>()[TokNum] = L;
  }

public:
  /// This is the "fully general" constructor that allows representation of
  /// strings formed from multiple concatenated tokens.
  static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
                               StringKind Kind, bool Pascal, QualType Ty,
                               const SourceLocation *Loc,
                               unsigned NumConcatenated);

  /// Simple constructor for string literals made from one token.
  static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
                               StringKind Kind, bool Pascal, QualType Ty,
                               SourceLocation Loc) {
    return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1);
  }

  /// Construct an empty string literal.
  static StringLiteral *CreateEmpty(const ASTContext &Ctx,
                                    unsigned NumConcatenated, unsigned Length,
                                    unsigned CharByteWidth);

  StringRef getString() const {
    assert(getCharByteWidth() == 1 &&
           "This function is used in places that assume strings use char");
    return StringRef(getStrDataAsChar(), getByteLength());
  }

  /// Allow access to clients that need the byte representation, such as
  /// ASTWriterStmt::VisitStringLiteral().
  StringRef getBytes() const {
    // FIXME: StringRef may not be the right type to use as a result for this.
    return StringRef(getStrDataAsChar(), getByteLength());
  }

  void outputString(raw_ostream &OS) const;

  uint32_t getCodeUnit(size_t i) const {
    assert(i < getLength() && "out of bounds access");
    switch (getCharByteWidth()) {
    case 1:
      return static_cast<unsigned char>(getStrDataAsChar()[i]);
    case 2:
      return getStrDataAsUInt16()[i];
    case 4:
      return getStrDataAsUInt32()[i];
    }
    llvm_unreachable("Unsupported character width!");
  }

  unsigned getByteLength() const { return getCharByteWidth() * getLength(); }
  unsigned getLength() const { return *getTrailingObjects<unsigned>(); }
  unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }

  StringKind getKind() const {
    return static_cast<StringKind>(StringLiteralBits.Kind);
  }

  bool isAscii() const { return getKind() == Ascii; }
  bool isWide() const { return getKind() == Wide; }
  bool isUTF8() const { return getKind() == UTF8; }
  bool isUTF16() const { return getKind() == UTF16; }
  bool isUTF32() const { return getKind() == UTF32; }
  bool isPascal() const { return StringLiteralBits.IsPascal; }

  bool containsNonAscii() const {
    for (auto c : getString())
      if (!isASCII(c))
        return true;
    return false;
  }

  bool containsNonAsciiOrNull() const {
    for (auto c : getString())
      if (!isASCII(c) || !c)
        return true;
    return false;
  }

  /// getNumConcatenated - Get the number of string literal tokens that were
  /// concatenated in translation phase #6 to form this string literal.
  unsigned getNumConcatenated() const {
    return StringLiteralBits.NumConcatenated;
  }

  /// Get one of the string literal token.
  SourceLocation getStrTokenLoc(unsigned TokNum) const {
    assert(TokNum < getNumConcatenated() && "Invalid tok number");
    return getTrailingObjects<SourceLocation>()[TokNum];
  }

  /// getLocationOfByte - Return a source location that points to the specified
  /// byte of this string literal.
  ///
  /// Strings are amazingly complex.  They can be formed from multiple tokens
  /// and can have escape sequences in them in addition to the usual trigraph
  /// and escaped newline business.  This routine handles this complexity.
  ///
  SourceLocation
  getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
                    const LangOptions &Features, const TargetInfo &Target,
                    unsigned *StartToken = nullptr,
                    unsigned *StartTokenByteOffset = nullptr) const;

  typedef const SourceLocation *tokloc_iterator;

  tokloc_iterator tokloc_begin() const {
    return getTrailingObjects<SourceLocation>();
  }

  tokloc_iterator tokloc_end() const {
    return getTrailingObjects<SourceLocation>() + getNumConcatenated();
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return *tokloc_begin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return *(tokloc_end() - 1); }

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

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

/// [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr final
    : public Expr,
      private llvm::TrailingObjects<PredefinedExpr, Stmt *> {
  friend class ASTStmtReader;
  friend TrailingObjects;

  // PredefinedExpr is optionally followed by a single trailing
  // "Stmt *" for the predefined identifier. It is present if and only if
  // hasFunctionName() is true and is always a "StringLiteral *".

public:
  enum IdentKind {
    Func,
    Function,
    LFunction, // Same as Function, but as wide string.
    FuncDName,
    FuncSig,
    LFuncSig, // Same as FuncSig, but as as wide string
    PrettyFunction,
    /// The same as PrettyFunction, except that the
    /// 'virtual' keyword is omitted for virtual member functions.
    PrettyFunctionNoVirtual
  };

private:
  PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
                 StringLiteral *SL);

  explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);

  /// True if this PredefinedExpr has storage for a function name.
  bool hasFunctionName() const { return PredefinedExprBits.HasFunctionName; }

  void setFunctionName(StringLiteral *SL) {
    assert(hasFunctionName() &&
           "This PredefinedExpr has no storage for a function name!");
    *getTrailingObjects<Stmt *>() = SL;
  }

public:
  /// Create a PredefinedExpr.
  static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
                                QualType FNTy, IdentKind IK, StringLiteral *SL);

  /// Create an empty PredefinedExpr.
  static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
                                     bool HasFunctionName);

  IdentKind getIdentKind() const {
    return static_cast<IdentKind>(PredefinedExprBits.Kind);
  }

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

  StringLiteral *getFunctionName() {
    return hasFunctionName()
               ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
               : nullptr;
  }

  const StringLiteral *getFunctionName() const {
    return hasFunctionName()
               ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
               : nullptr;
  }

  static StringRef getIdentKindName(IdentKind IK);
  StringRef getIdentKindName() const {
    return getIdentKindName(getIdentKind());
  }

  static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);

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

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

  // Iterators
  child_range children() {
    return child_range(getTrailingObjects<Stmt *>(),
                       getTrailingObjects<Stmt *>() + hasFunctionName());
  }

  const_child_range children() const {
    return const_child_range(getTrailingObjects<Stmt *>(),
                             getTrailingObjects<Stmt *>() + hasFunctionName());
  }
};

/// ParenExpr - This represents a parethesized expression, e.g. "(1)".  This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
  SourceLocation L, R;
  Stmt *Val;
public:
  ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
      : Expr(ParenExprClass, val->getType(), val->getValueKind(),
             val->getObjectKind()),
        L(l), R(r), Val(val) {
    setDependence(computeDependence(this));
  }

  /// Construct an empty parenthesized expression.
  explicit ParenExpr(EmptyShell Empty)
    : Expr(ParenExprClass, Empty) { }

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

  SourceLocation getBeginLoc() const LLVM_READONLY { return L; }
  SourceLocation getEndLoc() const LLVM_READONLY { return R; }

  /// Get the location of the left parentheses '('.
  SourceLocation getLParen() const { return L; }
  void setLParen(SourceLocation Loc) { L = Loc; }

  /// Get the location of the right parentheses ')'.
  SourceLocation getRParen() const { return R; }
  void setRParen(SourceLocation Loc) { R = Loc; }

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

  // Iterators
  child_range children() { return child_range(&Val, &Val+1); }
  const_child_range children() const {
    return const_child_range(&Val, &Val + 1);
  }
};

/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
///
/// Notes on various nodes:
///
/// Real/Imag - These return the real/imag part of a complex operand.  If
///   applied to a non-complex value, the former returns its operand and the
///   later returns zero in the type of the operand.
///
class UnaryOperator final
    : public Expr,
      private llvm::TrailingObjects<UnaryOperator, FPOptionsOverride> {
  Stmt *Val;

  size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const {
    return UnaryOperatorBits.HasFPFeatures ? 1 : 0;
  }

  FPOptionsOverride &getTrailingFPFeatures() {
    assert(UnaryOperatorBits.HasFPFeatures);
    return *getTrailingObjects<FPOptionsOverride>();
  }

  const FPOptionsOverride &getTrailingFPFeatures() const {
    assert(UnaryOperatorBits.HasFPFeatures);
    return *getTrailingObjects<FPOptionsOverride>();
  }

public:
  typedef UnaryOperatorKind Opcode;

protected:
  UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, QualType type,
                ExprValueKind VK, ExprObjectKind OK, SourceLocation l,
                bool CanOverflow, FPOptionsOverride FPFeatures);

  /// Build an empty unary operator.
  explicit UnaryOperator(bool HasFPFeatures, EmptyShell Empty)
      : Expr(UnaryOperatorClass, Empty) {
    UnaryOperatorBits.Opc = UO_AddrOf;
    UnaryOperatorBits.HasFPFeatures = HasFPFeatures;
  }

public:
  static UnaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures);

  static UnaryOperator *Create(const ASTContext &C, Expr *input, Opcode opc,
                               QualType type, ExprValueKind VK,
                               ExprObjectKind OK, SourceLocation l,
                               bool CanOverflow, FPOptionsOverride FPFeatures);

  Opcode getOpcode() const {
    return static_cast<Opcode>(UnaryOperatorBits.Opc);
  }
  void setOpcode(Opcode Opc) { UnaryOperatorBits.Opc = Opc; }

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

  /// getOperatorLoc - Return the location of the operator.
  SourceLocation getOperatorLoc() const { return UnaryOperatorBits.Loc; }
  void setOperatorLoc(SourceLocation L) { UnaryOperatorBits.Loc = L; }

  /// Returns true if the unary operator can cause an overflow. For instance,
  ///   signed int i = INT_MAX; i++;
  ///   signed char c = CHAR_MAX; c++;
  /// Due to integer promotions, c++ is promoted to an int before the postfix
  /// increment, and the result is an int that cannot overflow. However, i++
  /// can overflow.
  bool canOverflow() const { return UnaryOperatorBits.CanOverflow; }
  void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; }

  // Get the FP contractability status of this operator. Only meaningful for
  // operations on floating point types.
  bool isFPContractableWithinStatement(const LangOptions &LO) const {
    return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
  }

  // Get the FENV_ACCESS status of this operator. Only meaningful for
  // operations on floating point types.
  bool isFEnvAccessOn(const LangOptions &LO) const {
    return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
  }

  /// isPostfix - Return true if this is a postfix operation, like x++.
  static bool isPostfix(Opcode Op) {
    return Op == UO_PostInc || Op == UO_PostDec;
  }

  /// isPrefix - Return true if this is a prefix operation, like --x.
  static bool isPrefix(Opcode Op) {
    return Op == UO_PreInc || Op == UO_PreDec;
  }

  bool isPrefix() const { return isPrefix(getOpcode()); }
  bool isPostfix() const { return isPostfix(getOpcode()); }

  static bool isIncrementOp(Opcode Op) {
    return Op == UO_PreInc || Op == UO_PostInc;
  }
  bool isIncrementOp() const {
    return isIncrementOp(getOpcode());
  }

  static bool isDecrementOp(Opcode Op) {
    return Op == UO_PreDec || Op == UO_PostDec;
  }
  bool isDecrementOp() const {
    return isDecrementOp(getOpcode());
  }

  static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
  bool isIncrementDecrementOp() const {
    return isIncrementDecrementOp(getOpcode());
  }

  static bool isArithmeticOp(Opcode Op) {
    return Op >= UO_Plus && Op <= UO_LNot;
  }
  bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }

  /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
  /// corresponds to, e.g. "sizeof" or "[pre]++"
  static StringRef getOpcodeStr(Opcode Op);

  /// Retrieve the unary opcode that corresponds to the given
  /// overloaded operator.
  static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);

  /// Retrieve the overloaded operator kind that corresponds to
  /// the given unary opcode.
  static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return isPostfix() ? Val->getBeginLoc() : getOperatorLoc();
  }
  SourceLocation getEndLoc() const LLVM_READONLY {
    return isPostfix() ? getOperatorLoc() : Val->getEndLoc();
  }
  SourceLocation getExprLoc() const { return getOperatorLoc(); }

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

  // Iterators
  child_range children() { return child_range(&Val, &Val+1); }
  const_child_range children() const {
    return const_child_range(&Val, &Val + 1);
  }

  /// Is FPFeatures in Trailing Storage?
  bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; }

  /// Get FPFeatures from trailing storage.
  FPOptionsOverride getStoredFPFeatures() const {
    return getTrailingFPFeatures();
  }

protected:
  /// Set FPFeatures in trailing storage, used only by Serialization
  void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }

public:
  // Get the FP features status of this operator. Only meaningful for
  // operations on floating point types.
  FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
    if (UnaryOperatorBits.HasFPFeatures)
      return getStoredFPFeatures().applyOverrides(LO);
    return FPOptions::defaultWithoutTrailingStorage(LO);
  }
  FPOptionsOverride getFPOptionsOverride() const {
    if (UnaryOperatorBits.HasFPFeatures)
      return getStoredFPFeatures();
    return FPOptionsOverride();
  }

  friend TrailingObjects;
  friend class ASTReader;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// Helper class for OffsetOfExpr.

// __builtin_offsetof(type, identifier(.identifier|[expr])*)
class OffsetOfNode {
public:
  /// The kind of offsetof node we have.
  enum Kind {
    /// An index into an array.
    Array = 0x00,
    /// A field.
    Field = 0x01,
    /// A field in a dependent type, known only by its name.
    Identifier = 0x02,
    /// An implicit indirection through a C++ base class, when the
    /// field found is in a base class.
    Base = 0x03
  };

private:
  enum { MaskBits = 2, Mask = 0x03 };

  /// The source range that covers this part of the designator.
  SourceRange Range;

  /// The data describing the designator, which comes in three
  /// different forms, depending on the lower two bits.
  ///   - An unsigned index into the array of Expr*'s stored after this node
  ///     in memory, for [constant-expression] designators.
  ///   - A FieldDecl*, for references to a known field.
  ///   - An IdentifierInfo*, for references to a field with a given name
  ///     when the class type is dependent.
  ///   - A CXXBaseSpecifier*, for references that look at a field in a
  ///     base class.
  uintptr_t Data;

public:
  /// Create an offsetof node that refers to an array element.
  OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
               SourceLocation RBracketLoc)
      : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}

  /// Create an offsetof node that refers to a field.
  OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
      : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
        Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}

  /// Create an offsetof node that refers to an identifier.
  OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
               SourceLocation NameLoc)
      : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
        Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}

  /// Create an offsetof node that refers into a C++ base class.
  explicit OffsetOfNode(const CXXBaseSpecifier *Base)
      : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}

  /// Determine what kind of offsetof node this is.
  Kind getKind() const { return static_cast<Kind>(Data & Mask); }

  /// For an array element node, returns the index into the array
  /// of expressions.
  unsigned getArrayExprIndex() const {
    assert(getKind() == Array);
    return Data >> 2;
  }

  /// For a field offsetof node, returns the field.
  FieldDecl *getField() const {
    assert(getKind() == Field);
    return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
  }

  /// For a field or identifier offsetof node, returns the name of
  /// the field.
  IdentifierInfo *getFieldName() const;

  /// For a base class node, returns the base specifier.
  CXXBaseSpecifier *getBase() const {
    assert(getKind() == Base);
    return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
  }

  /// Retrieve the source range that covers this offsetof node.
  ///
  /// For an array element node, the source range contains the locations of
  /// the square brackets. For a field or identifier node, the source range
  /// contains the location of the period (if there is one) and the
  /// identifier.
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
};

/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
/// struct S {
///   float f;
///   double d;
/// };
/// struct T {
///   int i;
///   struct S s[10];
/// };
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).

class OffsetOfExpr final
    : public Expr,
      private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
  SourceLocation OperatorLoc, RParenLoc;
  // Base type;
  TypeSourceInfo *TSInfo;
  // Number of sub-components (i.e. instances of OffsetOfNode).
  unsigned NumComps;
  // Number of sub-expressions (i.e. array subscript expressions).
  unsigned NumExprs;

  size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
    return NumComps;
  }

  OffsetOfExpr(const ASTContext &C, QualType type,
               SourceLocation OperatorLoc, TypeSourceInfo *tsi,
               ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
               SourceLocation RParenLoc);

  explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
    : Expr(OffsetOfExprClass, EmptyShell()),
      TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}

public:

  static OffsetOfExpr *Create(const ASTContext &C, QualType type,
                              SourceLocation OperatorLoc, TypeSourceInfo *tsi,
                              ArrayRef<OffsetOfNode> comps,
                              ArrayRef<Expr*> exprs, SourceLocation RParenLoc);

  static OffsetOfExpr *CreateEmpty(const ASTContext &C,
                                   unsigned NumComps, unsigned NumExprs);

  /// getOperatorLoc - Return the location of the operator.
  SourceLocation getOperatorLoc() const { return OperatorLoc; }
  void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }

  /// Return the location of the right parentheses.
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation R) { RParenLoc = R; }

  TypeSourceInfo *getTypeSourceInfo() const {
    return TSInfo;
  }
  void setTypeSourceInfo(TypeSourceInfo *tsi) {
    TSInfo = tsi;
  }

  const OffsetOfNode &getComponent(unsigned Idx) const {
    assert(Idx < NumComps && "Subscript out of range");
    return getTrailingObjects<OffsetOfNode>()[Idx];
  }

  void setComponent(unsigned Idx, OffsetOfNode ON) {
    assert(Idx < NumComps && "Subscript out of range");
    getTrailingObjects<OffsetOfNode>()[Idx] = ON;
  }

  unsigned getNumComponents() const {
    return NumComps;
  }

  Expr* getIndexExpr(unsigned Idx) {
    assert(Idx < NumExprs && "Subscript out of range");
    return getTrailingObjects<Expr *>()[Idx];
  }

  const Expr *getIndexExpr(unsigned Idx) const {
    assert(Idx < NumExprs && "Subscript out of range");
    return getTrailingObjects<Expr *>()[Idx];
  }

  void setIndexExpr(unsigned Idx, Expr* E) {
    assert(Idx < NumComps && "Subscript out of range");
    getTrailingObjects<Expr *>()[Idx] = E;
  }

  unsigned getNumExpressions() const {
    return NumExprs;
  }

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

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

  // Iterators
  child_range children() {
    Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
    return child_range(begin, begin + NumExprs);
  }
  const_child_range children() const {
    Stmt *const *begin =
        reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
    return const_child_range(begin, begin + NumExprs);
  }
  friend TrailingObjects;
};

/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
/// expression operand.  Used for sizeof/alignof (C99 6.5.3.4) and
/// vec_step (OpenCL 1.1 6.11.12).
class UnaryExprOrTypeTraitExpr : public Expr {
  union {
    TypeSourceInfo *Ty;
    Stmt *Ex;
  } Argument;
  SourceLocation OpLoc, RParenLoc;

public:
  UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
                           QualType resultType, SourceLocation op,
                           SourceLocation rp)
      : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary),
        OpLoc(op), RParenLoc(rp) {
    assert(ExprKind <= UETT_Last && "invalid enum value!");
    UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
    assert(static_cast<unsigned>(ExprKind) ==
               UnaryExprOrTypeTraitExprBits.Kind &&
           "UnaryExprOrTypeTraitExprBits.Kind overflow!");
    UnaryExprOrTypeTraitExprBits.IsType = true;
    Argument.Ty = TInfo;
    setDependence(computeDependence(this));
  }

  UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
                           QualType resultType, SourceLocation op,
                           SourceLocation rp);

  /// Construct an empty sizeof/alignof expression.
  explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
    : Expr(UnaryExprOrTypeTraitExprClass, Empty) { }

  UnaryExprOrTypeTrait getKind() const {
    return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind);
  }
  void setKind(UnaryExprOrTypeTrait K) {
    assert(K <= UETT_Last && "invalid enum value!");
    UnaryExprOrTypeTraitExprBits.Kind = K;
    assert(static_cast<unsigned>(K) == UnaryExprOrTypeTraitExprBits.Kind &&
           "UnaryExprOrTypeTraitExprBits.Kind overflow!");
  }

  bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; }
  QualType getArgumentType() const {
    return getArgumentTypeInfo()->getType();
  }
  TypeSourceInfo *getArgumentTypeInfo() const {
    assert(isArgumentType() && "calling getArgumentType() when arg is expr");
    return Argument.Ty;
  }
  Expr *getArgumentExpr() {
    assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
    return static_cast<Expr*>(Argument.Ex);
  }
  const Expr *getArgumentExpr() const {
    return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
  }

  void setArgument(Expr *E) {
    Argument.Ex = E;
    UnaryExprOrTypeTraitExprBits.IsType = false;
  }
  void setArgument(TypeSourceInfo *TInfo) {
    Argument.Ty = TInfo;
    UnaryExprOrTypeTraitExprBits.IsType = true;
  }

  /// Gets the argument type, or the type of the argument expression, whichever
  /// is appropriate.
  QualType getTypeOfArgument() const {
    return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
  }

  SourceLocation getOperatorLoc() const { return OpLoc; }
  void setOperatorLoc(SourceLocation L) { OpLoc = L; }

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

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

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

  // Iterators
  child_range children();
  const_child_range children() const;
};

//===----------------------------------------------------------------------===//
// Postfix Operators.
//===----------------------------------------------------------------------===//

/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
  enum { LHS, RHS, END_EXPR };
  Stmt *SubExprs[END_EXPR];

  bool lhsIsBase() const { return getRHS()->getType()->isIntegerType(); }

public:
  ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, ExprValueKind VK,
                     ExprObjectKind OK, SourceLocation rbracketloc)
      : Expr(ArraySubscriptExprClass, t, VK, OK) {
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
    ArrayOrMatrixSubscriptExprBits.RBracketLoc = rbracketloc;
    setDependence(computeDependence(this));
  }

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

  /// An array access can be written A[4] or 4[A] (both are equivalent).
  /// - getBase() and getIdx() always present the normalized view: A[4].
  ///    In this case getBase() returns "A" and getIdx() returns "4".
  /// - getLHS() and getRHS() present the syntactic view. e.g. for
  ///    4[A] getLHS() returns "4".
  /// Note: Because vector element access is also written A[4] we must
  /// predicate the format conversion in getBase and getIdx only on the
  /// the type of the RHS, as it is possible for the LHS to be a vector of
  /// integer type
  Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); }
  const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
  void setLHS(Expr *E) { SubExprs[LHS] = E; }

  Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
  const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
  void setRHS(Expr *E) { SubExprs[RHS] = E; }

  Expr *getBase() { return lhsIsBase() ? getLHS() : getRHS(); }
  const Expr *getBase() const { return lhsIsBase() ? getLHS() : getRHS(); }

  Expr *getIdx() { return lhsIsBase() ? getRHS() : getLHS(); }
  const Expr *getIdx() const { return lhsIsBase() ? getRHS() : getLHS(); }

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

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

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

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

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

/// MatrixSubscriptExpr - Matrix subscript expression for the MatrixType
/// extension.
/// MatrixSubscriptExpr can be either incomplete (only Base and RowIdx are set
/// so far, the type is IncompleteMatrixIdx) or complete (Base, RowIdx and
/// ColumnIdx refer to valid expressions). Incomplete matrix expressions only
/// exist during the initial construction of the AST.
class MatrixSubscriptExpr : public Expr {
  enum { BASE, ROW_IDX, COLUMN_IDX, END_EXPR };
  Stmt *SubExprs[END_EXPR];

public:
  MatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, QualType T,
                      SourceLocation RBracketLoc)
      : Expr(MatrixSubscriptExprClass, T, Base->getValueKind(),
             OK_MatrixComponent) {
    SubExprs[BASE] = Base;
    SubExprs[ROW_IDX] = RowIdx;
    SubExprs[COLUMN_IDX] = ColumnIdx;
    ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc;
    setDependence(computeDependence(this));
  }

  /// Create an empty matrix subscript expression.
  explicit MatrixSubscriptExpr(EmptyShell Shell)
      : Expr(MatrixSubscriptExprClass, Shell) {}

  bool isIncomplete() const {
    bool IsIncomplete = hasPlaceholderType(BuiltinType::IncompleteMatrixIdx);
    assert((SubExprs[COLUMN_IDX] || IsIncomplete) &&
           "expressions without column index must be marked as incomplete");
    return IsIncomplete;
  }
  Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
  const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
  void setBase(Expr *E) { SubExprs[BASE] = E; }

  Expr *getRowIdx() { return cast<Expr>(SubExprs[ROW_IDX]); }
  const Expr *getRowIdx() const { return cast<Expr>(SubExprs[ROW_IDX]); }
  void setRowIdx(Expr *E) { SubExprs[ROW_IDX] = E; }

  Expr *getColumnIdx() { return cast_or_null<Expr>(SubExprs[COLUMN_IDX]); }
  const Expr *getColumnIdx() const {
    assert(!isIncomplete() &&
           "cannot get the column index of an incomplete expression");
    return cast<Expr>(SubExprs[COLUMN_IDX]);
  }
  void setColumnIdx(Expr *E) { SubExprs[COLUMN_IDX] = E; }

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

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

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

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

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

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

/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
/// results in a function call. For example, CXXOperatorCallExpr is
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
  enum { FN = 0, PREARGS_START = 1 };

  /// The number of arguments in the call expression.
  unsigned NumArgs;

  /// The location of the right parenthese. This has a different meaning for
  /// the derived classes of CallExpr.
  SourceLocation RParenLoc;

  // CallExpr store some data in trailing objects. However since CallExpr
  // is used a base of other expression classes we cannot use
  // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic
  // and casts.
  //
  // The trailing objects are in order:
  //
  // * A single "Stmt *" for the callee expression.
  //
  // * An array of getNumPreArgs() "Stmt *" for the pre-argument expressions.
  //
  // * An array of getNumArgs() "Stmt *" for the argument expressions.
  //
  // * An optional of type FPOptionsOverride.
  //
  // Note that we store the offset in bytes from the this pointer to the start
  // of the trailing objects. It would be perfectly possible to compute it
  // based on the dynamic kind of the CallExpr. However 1.) we have plenty of
  // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to
  // compute this once and then load the offset from the bit-fields of Stmt,
  // instead of re-computing the offset each time the trailing objects are
  // accessed.

  /// Return a pointer to the start of the trailing array of "Stmt *".
  Stmt **getTrailingStmts() {
    return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) +
                                     CallExprBits.OffsetToTrailingObjects);
  }
  Stmt *const *getTrailingStmts() const {
    return const_cast<CallExpr *>(this)->getTrailingStmts();
  }

  /// Map a statement class to the appropriate offset in bytes from the
  /// this pointer to the trailing objects.
  static unsigned offsetToTrailingObjects(StmtClass SC);

  unsigned getSizeOfTrailingStmts() const {
    return (1 + getNumPreArgs() + getNumArgs()) * sizeof(Stmt *);
  }

  size_t getOffsetOfTrailingFPFeatures() const {
    assert(hasStoredFPFeatures());
    return CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts();
  }

public:
  enum class ADLCallKind : bool { NotADL, UsesADL };
  static constexpr ADLCallKind NotADL = ADLCallKind::NotADL;
  static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL;

protected:
  /// Build a call expression, assuming that appropriate storage has been
  /// allocated for the trailing objects.
  CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
           ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
           SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
           unsigned MinNumArgs, ADLCallKind UsesADL);

  /// Build an empty call expression, for deserialization.
  CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
           bool hasFPFeatures, EmptyShell Empty);

  /// Return the size in bytes needed for the trailing objects.
  /// Used by the derived classes to allocate the right amount of storage.
  static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs,
                                        bool HasFPFeatures) {
    return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *) +
           HasFPFeatures * sizeof(FPOptionsOverride);
  }

  Stmt *getPreArg(unsigned I) {
    assert(I < getNumPreArgs() && "Prearg access out of range!");
    return getTrailingStmts()[PREARGS_START + I];
  }
  const Stmt *getPreArg(unsigned I) const {
    assert(I < getNumPreArgs() && "Prearg access out of range!");
    return getTrailingStmts()[PREARGS_START + I];
  }
  void setPreArg(unsigned I, Stmt *PreArg) {
    assert(I < getNumPreArgs() && "Prearg access out of range!");
    getTrailingStmts()[PREARGS_START + I] = PreArg;
  }

  unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }

  /// Return a pointer to the trailing FPOptions
  FPOptionsOverride *getTrailingFPFeatures() {
    assert(hasStoredFPFeatures());
    return reinterpret_cast<FPOptionsOverride *>(
        reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects +
        getSizeOfTrailingStmts());
  }
  const FPOptionsOverride *getTrailingFPFeatures() const {
    assert(hasStoredFPFeatures());
    return reinterpret_cast<const FPOptionsOverride *>(
        reinterpret_cast<const char *>(this) +
        CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts());
  }

public:
  /// Create a call expression.
  /// \param Fn     The callee expression,
  /// \param Args   The argument array,
  /// \param Ty     The type of the call expression (which is *not* the return
  ///               type in general),
  /// \param VK     The value kind of the call expression (lvalue, rvalue, ...),
  /// \param RParenLoc  The location of the right parenthesis in the call
  ///                   expression.
  /// \param FPFeatures Floating-point features associated with the call,
  /// \param MinNumArgs Specifies the minimum number of arguments. The actual
  ///                   number of arguments will be the greater of Args.size()
  ///                   and MinNumArgs. This is used in a few places to allocate
  ///                   enough storage for the default arguments.
  /// \param UsesADL    Specifies whether the callee was found through
  ///                   argument-dependent lookup.
  ///
  /// Note that you can use CreateTemporary if you need a temporary call
  /// expression on the stack.
  static CallExpr *Create(const ASTContext &Ctx, Expr *Fn,
                          ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
                          SourceLocation RParenLoc,
                          FPOptionsOverride FPFeatures, unsigned MinNumArgs = 0,
                          ADLCallKind UsesADL = NotADL);

  /// Create a temporary call expression with no arguments in the memory
  /// pointed to by Mem. Mem must points to at least sizeof(CallExpr)
  /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr):
  ///
  /// \code{.cpp}
  ///   alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)];
  ///   CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc);
  /// \endcode
  static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
                                   ExprValueKind VK, SourceLocation RParenLoc,
                                   ADLCallKind UsesADL = NotADL);

  /// Create an empty call expression, for deserialization.
  static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
                               bool HasFPFeatures, EmptyShell Empty);

  Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); }
  const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); }
  void setCallee(Expr *F) { getTrailingStmts()[FN] = F; }

  ADLCallKind getADLCallKind() const {
    return static_cast<ADLCallKind>(CallExprBits.UsesADL);
  }
  void setADLCallKind(ADLCallKind V = UsesADL) {
    CallExprBits.UsesADL = static_cast<bool>(V);
  }
  bool usesADL() const { return getADLCallKind() == UsesADL; }

  bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }

  Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); }
  const Decl *getCalleeDecl() const {
    return getCallee()->getReferencedDeclOfCallee();
  }

  /// If the callee is a FunctionDecl, return it. Otherwise return null.
  FunctionDecl *getDirectCallee() {
    return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
  }
  const FunctionDecl *getDirectCallee() const {
    return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
  }

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

  /// Retrieve the call arguments.
  Expr **getArgs() {
    return reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START +
                                     getNumPreArgs());
  }
  const Expr *const *getArgs() const {
    return reinterpret_cast<const Expr *const *>(
        getTrailingStmts() + PREARGS_START + getNumPreArgs());
  }

  /// getArg - 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];
  }

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

  /// Reduce the number of arguments in this call expression. This is used for
  /// example during error recovery to drop extra arguments. There is no way
  /// to perform the opposite because: 1.) We don't track how much storage
  /// we have for the argument array 2.) This would potentially require growing
  /// the argument array, something we cannot support since the arguments are
  /// stored in a trailing array.
  void shrinkNumArgs(unsigned NewNumArgs) {
    assert((NewNumArgs <= getNumArgs()) &&
           "shrinkNumArgs cannot increase the number of arguments!");
    NumArgs = NewNumArgs;
  }

  /// Bluntly set a new number of arguments without doing any checks whatsoever.
  /// Only used during construction of a CallExpr in a few places in Sema.
  /// FIXME: Find a way to remove it.
  void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; }

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

  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 getTrailingStmts() + PREARGS_START + getNumPreArgs();
  }
  arg_iterator arg_end() { return arg_begin() + getNumArgs(); }

  const_arg_iterator arg_begin() const {
    return getTrailingStmts() + PREARGS_START + getNumPreArgs();
  }
  const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); }

  /// This method provides fast access to all the subexpressions of
  /// a CallExpr without going through the slower virtual child_iterator
  /// interface.  This provides efficient reverse iteration of the
  /// subexpressions.  This is currently used for CFG construction.
  ArrayRef<Stmt *> getRawSubExprs() {
    return llvm::makeArrayRef(getTrailingStmts(),
                              PREARGS_START + getNumPreArgs() + getNumArgs());
  }

  /// getNumCommas - Return the number of commas that must have been present in
  /// this function call.
  unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }

  /// Get FPOptionsOverride from trailing storage.
  FPOptionsOverride getStoredFPFeatures() const {
    assert(hasStoredFPFeatures());
    return *getTrailingFPFeatures();
  }
  /// Set FPOptionsOverride in trailing storage. Used only by Serialization.
  void setStoredFPFeatures(FPOptionsOverride F) {
    assert(hasStoredFPFeatures());
    *getTrailingFPFeatures() = F;
  }

  // Get the FP features status of this operator. Only meaningful for
  // operations on floating point types.
  FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
    if (hasStoredFPFeatures())
      return getStoredFPFeatures().applyOverrides(LO);
    return FPOptions::defaultWithoutTrailingStorage(LO);
  }

  FPOptionsOverride getFPFeatures() const {
    if (hasStoredFPFeatures())
      return getStoredFPFeatures();
    return FPOptionsOverride();
  }

  /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
  /// of the callee. If not, return 0.
  unsigned getBuiltinCallee() const;

  /// Returns \c true if this is a call to a builtin which does not
  /// evaluate side-effects within its arguments.
  bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;

  /// getCallReturnType - Get the return type of the call expr. This is not
  /// always the type of the expr itself, if the return type is a reference
  /// type.
  QualType getCallReturnType(const ASTContext &Ctx) const;

  /// Returns the WarnUnusedResultAttr that is either declared on the called
  /// function, or its return type declaration.
  const Attr *getUnusedResultAttr(const ASTContext &Ctx) const;

  /// Returns true if this call expression should warn on unused results.
  bool hasUnusedResultAttr(const ASTContext &Ctx) const {
    return getUnusedResultAttr(Ctx) != nullptr;
  }

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

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

  /// Return true if this is a call to __assume() or __builtin_assume() with
  /// a non-value-dependent constant parameter evaluating as false.
  bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;

  /// Used by Sema to implement MSVC-compatible delayed name lookup.
  /// (Usually Exprs themselves should set dependence).
  void markDependentForPostponedNameLookup() {
    setDependence(getDependence() | ExprDependence::TypeValueInstantiation);
  }

  bool isCallToStdMove() const {
    const FunctionDecl *FD = getDirectCallee();
    return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
           FD->getIdentifier() && FD->getIdentifier()->isStr("move");
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() >= firstCallExprConstant &&
           T->getStmtClass() <= lastCallExprConstant;
  }

  // Iterators
  child_range children() {
    return child_range(getTrailingStmts(), getTrailingStmts() + PREARGS_START +
                                               getNumPreArgs() + getNumArgs());
  }

  const_child_range children() const {
    return const_child_range(getTrailingStmts(),
                             getTrailingStmts() + PREARGS_START +
                                 getNumPreArgs() + getNumArgs());
  }
};

/// Extra data stored in some MemberExpr objects.
struct MemberExprNameQualifier {
  /// The nested-name-specifier that qualifies the name, including
  /// source-location information.
  NestedNameSpecifierLoc QualifierLoc;

  /// The DeclAccessPair through which the MemberDecl was found due to
  /// name qualifiers.
  DeclAccessPair FoundDecl;
};

/// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
///
class MemberExpr final
    : public Expr,
      private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
                                    ASTTemplateKWAndArgsInfo,
                                    TemplateArgumentLoc> {
  friend class ASTReader;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// Base - the expression for the base pointer or structure references.  In
  /// X.F, this is "X".
  Stmt *Base;

  /// MemberDecl - This is the decl being referenced by the field/member name.
  /// In X.F, this is the decl referenced by F.
  ValueDecl *MemberDecl;

  /// MemberDNLoc - Provides source/type location info for the
  /// declaration name embedded in MemberDecl.
  DeclarationNameLoc MemberDNLoc;

  /// MemberLoc - This is the location of the member name.
  SourceLocation MemberLoc;

  size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
    return hasQualifierOrFoundDecl();
  }

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

  bool hasQualifierOrFoundDecl() const {
    return MemberExprBits.HasQualifierOrFoundDecl;
  }

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

  MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
             ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
             QualType T, ExprValueKind VK, ExprObjectKind OK,
             NonOdrUseReason NOUR);
  MemberExpr(EmptyShell Empty)
      : Expr(MemberExprClass, Empty), Base(), MemberDecl() {}

public:
  static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow,
                            SourceLocation OperatorLoc,
                            NestedNameSpecifierLoc QualifierLoc,
                            SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
                            DeclAccessPair FoundDecl,
                            DeclarationNameInfo MemberNameInfo,
                            const TemplateArgumentListInfo *TemplateArgs,
                            QualType T, ExprValueKind VK, ExprObjectKind OK,
                            NonOdrUseReason NOUR);

  /// Create an implicit MemberExpr, with no location, qualifier, template
  /// arguments, and so on. Suitable only for non-static member access.
  static MemberExpr *CreateImplicit(const ASTContext &C, Expr *Base,
                                    bool IsArrow, ValueDecl *MemberDecl,
                                    QualType T, ExprValueKind VK,
                                    ExprObjectKind OK) {
    return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
                  SourceLocation(), MemberDecl,
                  DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()),
                  DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None);
  }

  static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
                                 bool HasFoundDecl,
                                 bool HasTemplateKWAndArgsInfo,
                                 unsigned NumTemplateArgs);

  void setBase(Expr *E) { Base = E; }
  Expr *getBase() const { return cast<Expr>(Base); }

  /// Retrieve the member declaration to which this expression refers.
  ///
  /// The returned declaration will be a FieldDecl or (in C++) a VarDecl (for
  /// static data members), a CXXMethodDecl, or an EnumConstantDecl.
  ValueDecl *getMemberDecl() const { return MemberDecl; }
  void setMemberDecl(ValueDecl *D);

  /// Retrieves the declaration found by lookup.
  DeclAccessPair getFoundDecl() const {
    if (!hasQualifierOrFoundDecl())
      return DeclAccessPair::make(getMemberDecl(),
                                  getMemberDecl()->getAccess());
    return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
  }

  /// 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 getQualifier() != nullptr; }

  /// If the member name was qualified, retrieves the
  /// nested-name-specifier that precedes the member name, with source-location
  /// information.
  NestedNameSpecifierLoc getQualifierLoc() const {
    if (!hasQualifierOrFoundDecl())
      return NestedNameSpecifierLoc();
    return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
  }

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

  /// 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 the member name was followed by an
  /// explicit template argument list.
  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()};
  }

  /// Retrieve the member declaration name info.
  DeclarationNameInfo getMemberNameInfo() const {
    return DeclarationNameInfo(MemberDecl->getDeclName(),
                               MemberLoc, MemberDNLoc);
  }

  SourceLocation getOperatorLoc() const { return MemberExprBits.OperatorLoc; }

  bool isArrow() const { return MemberExprBits.IsArrow; }
  void setArrow(bool A) { MemberExprBits.IsArrow = A; }

  /// getMemberLoc - Return the location of the "member", in X->F, it is the
  /// location of 'F'.
  SourceLocation getMemberLoc() const { return MemberLoc; }
  void setMemberLoc(SourceLocation L) { MemberLoc = L; }

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

  SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }

  /// Determine whether the base of this explicit is implicit.
  bool isImplicitAccess() const {
    return getBase() && getBase()->isImplicitCXXThis();
  }

  /// Returns true if this member expression refers to a method that
  /// was resolved from an overloaded set having size greater than 1.
  bool hadMultipleCandidates() const {
    return MemberExprBits.HadMultipleCandidates;
  }
  /// Sets the flag telling whether this expression refers to
  /// a method that was resolved from an overloaded set having size
  /// greater than 1.
  void setHadMultipleCandidates(bool V = true) {
    MemberExprBits.HadMultipleCandidates = V;
  }

  /// Returns true if virtual dispatch is performed.
  /// If the member access is fully qualified, (i.e. X::f()), virtual
  /// dispatching is not performed. In -fapple-kext mode qualified
  /// calls to virtual method will still go through the vtable.
  bool performsVirtualDispatch(const LangOptions &LO) const {
    return LO.AppleKext || !hasQualifier();
  }

  /// Is this expression a non-odr-use reference, and if so, why?
  /// This is only meaningful if the named member is a static member.
  NonOdrUseReason isNonOdrUse() const {
    return static_cast<NonOdrUseReason>(MemberExprBits.NonOdrUseReason);
  }

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

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

/// CompoundLiteralExpr - [C99 6.5.2.5]
///
class CompoundLiteralExpr : public Expr {
  /// LParenLoc - If non-null, this is the location of the left paren in a
  /// compound literal like "(int){4}".  This can be null if this is a
  /// synthesized compound expression.
  SourceLocation LParenLoc;

  /// The type as written.  This can be an incomplete array type, in
  /// which case the actual expression type will be different.
  /// The int part of the pair stores whether this expr is file scope.
  llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
  Stmt *Init;
public:
  CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
                      QualType T, ExprValueKind VK, Expr *init, bool fileScope)
      : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary),
        LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {
    setDependence(computeDependence(this));
  }

  /// Construct an empty compound literal.
  explicit CompoundLiteralExpr(EmptyShell Empty)
    : Expr(CompoundLiteralExprClass, Empty) { }

  const Expr *getInitializer() const { return cast<Expr>(Init); }
  Expr *getInitializer() { return cast<Expr>(Init); }
  void setInitializer(Expr *E) { Init = E; }

  bool isFileScope() const { return TInfoAndScope.getInt(); }
  void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }

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

  TypeSourceInfo *getTypeSourceInfo() const {
    return TInfoAndScope.getPointer();
  }
  void setTypeSourceInfo(TypeSourceInfo *tinfo) {
    TInfoAndScope.setPointer(tinfo);
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    // FIXME: Init should never be null.
    if (!Init)
      return SourceLocation();
    if (LParenLoc.isInvalid())
      return Init->getBeginLoc();
    return LParenLoc;
  }
  SourceLocation getEndLoc() const LLVM_READONLY {
    // FIXME: Init should never be null.
    if (!Init)
      return SourceLocation();
    return Init->getEndLoc();
  }

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

  // Iterators
  child_range children() { return child_range(&Init, &Init+1); }
  const_child_range children() const {
    return const_child_range(&Init, &Init + 1);
  }
};

/// CastExpr - Base class for type casts, including both implicit
/// casts (ImplicitCastExpr) and explicit casts that have some
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
  Stmt *Op;

  bool CastConsistency() const;

  const CXXBaseSpecifier * const *path_buffer() const {
    return const_cast<CastExpr*>(this)->path_buffer();
  }
  CXXBaseSpecifier **path_buffer();

  friend class ASTStmtReader;

protected:
  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
           Expr *op, unsigned BasePathSize, bool HasFPFeatures)
      : Expr(SC, ty, VK, OK_Ordinary), Op(op) {
    CastExprBits.Kind = kind;
    CastExprBits.PartOfExplicitCast = false;
    CastExprBits.BasePathSize = BasePathSize;
    assert((CastExprBits.BasePathSize == BasePathSize) &&
           "BasePathSize overflow!");
    setDependence(computeDependence(this));
    assert(CastConsistency());
    CastExprBits.HasFPFeatures = HasFPFeatures;
  }

  /// Construct an empty cast.
  CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize,
           bool HasFPFeatures)
      : Expr(SC, Empty) {
    CastExprBits.PartOfExplicitCast = false;
    CastExprBits.BasePathSize = BasePathSize;
    CastExprBits.HasFPFeatures = HasFPFeatures;
    assert((CastExprBits.BasePathSize == BasePathSize) &&
           "BasePathSize overflow!");
  }

  /// Return a pointer to the trailing FPOptions.
  /// \pre hasStoredFPFeatures() == true
  FPOptionsOverride *getTrailingFPFeatures();
  const FPOptionsOverride *getTrailingFPFeatures() const {
    return const_cast<CastExpr *>(this)->getTrailingFPFeatures();
  }

public:
  CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
  void setCastKind(CastKind K) { CastExprBits.Kind = K; }

  static const char *getCastKindName(CastKind CK);
  const char *getCastKindName() const { return getCastKindName(getCastKind()); }

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

  /// Retrieve the cast subexpression as it was written in the source
  /// code, looking through any implicit casts or other intermediate nodes
  /// introduced by semantic analysis.
  Expr *getSubExprAsWritten();
  const Expr *getSubExprAsWritten() const {
    return const_cast<CastExpr *>(this)->getSubExprAsWritten();
  }

  /// If this cast applies a user-defined conversion, retrieve the conversion
  /// function that it invokes.
  NamedDecl *getConversionFunction() const;

  typedef CXXBaseSpecifier **path_iterator;
  typedef const CXXBaseSpecifier *const *path_const_iterator;
  bool path_empty() const { return path_size() == 0; }
  unsigned path_size() const { return CastExprBits.BasePathSize; }
  path_iterator path_begin() { return path_buffer(); }
  path_iterator path_end() { return path_buffer() + path_size(); }
  path_const_iterator path_begin() const { return path_buffer(); }
  path_const_iterator path_end() const { return path_buffer() + path_size(); }

  llvm::iterator_range<path_iterator> path() {
    return llvm::make_range(path_begin(), path_end());
  }
  llvm::iterator_range<path_const_iterator> path() const {
    return llvm::make_range(path_begin(), path_end());
  }

  const FieldDecl *getTargetUnionField() const {
    assert(getCastKind() == CK_ToUnion);
    return getTargetFieldForToUnionCast(getType(), getSubExpr()->getType());
  }

  bool hasStoredFPFeatures() const { return CastExprBits.HasFPFeatures; }

  /// Get FPOptionsOverride from trailing storage.
  FPOptionsOverride getStoredFPFeatures() const {
    assert(hasStoredFPFeatures());
    return *getTrailingFPFeatures();
  }

  // Get the FP features status of this operation. Only meaningful for
  // operations on floating point types.
  FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
    if (hasStoredFPFeatures())
      return getStoredFPFeatures().applyOverrides(LO);
    return FPOptions::defaultWithoutTrailingStorage(LO);
  }

  FPOptionsOverride getFPFeatures() const {
    if (hasStoredFPFeatures())
      return getStoredFPFeatures();
    return FPOptionsOverride();
  }

  static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType,
                                                       QualType opType);
  static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD,
                                                       QualType opType);

  static bool classof(const Stmt *T) {
    return T->getStmtClass() >= firstCastExprConstant &&
           T->getStmtClass() <= lastCastExprConstant;
  }

  // Iterators
  child_range children() { return child_range(&Op, &Op+1); }
  const_child_range children() const { return const_child_range(&Op, &Op + 1); }
};

/// ImplicitCastExpr - Allows us to explicitly represent implicit type
/// conversions, which have no direct representation in the original
/// source code. For example: converting T[]->T*, void f()->void
/// (*f)(), float->double, short->int, etc.
///
/// In C, implicit casts always produce rvalues. However, in C++, an
/// implicit cast whose result is being bound to a reference will be
/// an lvalue or xvalue. For example:
///
/// @code
/// class Base { };
/// class Derived : public Base { };
/// Derived &&ref();
/// void f(Derived d) {
///   Base& b = d; // initializer is an ImplicitCastExpr
///                // to an lvalue of type Base
///   Base&& r = ref(); // initializer is an ImplicitCastExpr
///                     // to an xvalue of type Base
/// }
/// @endcode
class ImplicitCastExpr final
    : public CastExpr,
      private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *,
                                    FPOptionsOverride> {

  ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
                   unsigned BasePathLength, FPOptionsOverride FPO,
                   ExprValueKind VK)
      : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength,
                 FPO.requiresTrailingStorage()) {
    if (hasStoredFPFeatures())
      *getTrailingFPFeatures() = FPO;
  }

  /// Construct an empty implicit cast.
  explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize,
                            bool HasFPFeatures)
      : CastExpr(ImplicitCastExprClass, Shell, PathSize, HasFPFeatures) {}

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

public:
  enum OnStack_t { OnStack };
  ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
                   ExprValueKind VK, FPOptionsOverride FPO)
      : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0,
                 FPO.requiresTrailingStorage()) {
    if (hasStoredFPFeatures())
      *getTrailingFPFeatures() = FPO;
  }

  bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; }
  void setIsPartOfExplicitCast(bool PartOfExplicitCast) {
    CastExprBits.PartOfExplicitCast = PartOfExplicitCast;
  }

  static ImplicitCastExpr *Create(const ASTContext &Context, QualType T,
                                  CastKind Kind, Expr *Operand,
                                  const CXXCastPath *BasePath,
                                  ExprValueKind Cat, FPOptionsOverride FPO);

  static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
                                       unsigned PathSize, bool HasFPFeatures);

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

  friend TrailingObjects;
  friend class CastExpr;
};

/// ExplicitCastExpr - An explicit cast written in the source
/// code.
///
/// This class is effectively an abstract class, because it provides
/// the basic representation of an explicitly-written cast without
/// specifying which kind of cast (C cast, functional cast, static
/// cast, etc.) was written; specific derived classes represent the
/// particular style of cast and its location information.
///
/// Unlike implicit casts, explicit cast nodes have two different
/// types: the type that was written into the source code, and the
/// actual type of the expression as determined by semantic
/// analysis. These types may differ slightly. For example, in C++ one
/// can cast to a reference type, which indicates that the resulting
/// expression will be an lvalue or xvalue. The reference type, however,
/// will not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
  /// TInfo - Source type info for the (written) type
  /// this expression is casting to.
  TypeSourceInfo *TInfo;

protected:
  ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
                   CastKind kind, Expr *op, unsigned PathSize,
                   bool HasFPFeatures, TypeSourceInfo *writtenTy)
      : CastExpr(SC, exprTy, VK, kind, op, PathSize, HasFPFeatures),
        TInfo(writtenTy) {}

  /// Construct an empty explicit cast.
  ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize,
                   bool HasFPFeatures)
      : CastExpr(SC, Shell, PathSize, HasFPFeatures) {}

public:
  /// getTypeInfoAsWritten - Returns the type source info for the type
  /// that this expression is casting to.
  TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
  void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }

  /// getTypeAsWritten - Returns the type that this expression is
  /// casting to, as written in the source code.
  QualType getTypeAsWritten() const { return TInfo->getType(); }

  static bool classof(const Stmt *T) {
     return T->getStmtClass() >= firstExplicitCastExprConstant &&
            T->getStmtClass() <= lastExplicitCastExprConstant;
  }
};

/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
/// cast in C++ (C++ [expr.cast]), which uses the syntax
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *,
                                    FPOptionsOverride> {
  SourceLocation LPLoc; // the location of the left paren
  SourceLocation RPLoc; // the location of the right paren

  CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
                 unsigned PathSize, FPOptionsOverride FPO,
                 TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation r)
      : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
                         FPO.requiresTrailingStorage(), writtenTy),
        LPLoc(l), RPLoc(r) {
    if (hasStoredFPFeatures())
      *getTrailingFPFeatures() = FPO;
  }

  /// Construct an empty C-style explicit cast.
  explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize,
                          bool HasFPFeatures)
      : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize, HasFPFeatures) {}

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

public:
  static CStyleCastExpr *
  Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K,
         Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO,
         TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R);

  static CStyleCastExpr *CreateEmpty(const ASTContext &Context,
                                     unsigned PathSize, bool HasFPFeatures);

  SourceLocation getLParenLoc() const { return LPLoc; }
  void setLParenLoc(SourceLocation L) { LPLoc = L; }

  SourceLocation getRParenLoc() const { return RPLoc; }
  void setRParenLoc(SourceLocation L) { RPLoc = L; }

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

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

  friend TrailingObjects;
  friend class CastExpr;
};

/// A builtin binary operation expression such as "x + y" or "x <= y".
///
/// This expression node kind describes a builtin binary operation,
/// such as "x + y" for integer values "x" and "y". The operands will
/// already have been converted to appropriate types (e.g., by
/// performing promotions or conversions).
///
/// In C++, where operators may be overloaded, a different kind of
/// expression node (CXXOperatorCallExpr) is used to express the
/// invocation of an overloaded operator with operator syntax. Within
/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is
/// used to store an expression "x + y" depends on the subexpressions
/// for x and y. If neither x or y is type-dependent, and the "+"
/// operator resolves to a built-in operation, BinaryOperator will be
/// used to express the computation (x and y may still be
/// value-dependent). If either x or y is type-dependent, or if the
/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will
/// be used to express the computation.
class BinaryOperator : public Expr {
  enum { LHS, RHS, END_EXPR };
  Stmt *SubExprs[END_EXPR];

public:
  typedef BinaryOperatorKind Opcode;

protected:
  size_t offsetOfTrailingStorage() const;

  /// Return a pointer to the trailing FPOptions
  FPOptionsOverride *getTrailingFPFeatures() {
    assert(BinaryOperatorBits.HasFPFeatures);
    return reinterpret_cast<FPOptionsOverride *>(
        reinterpret_cast<char *>(this) + offsetOfTrailingStorage());
  }
  const FPOptionsOverride *getTrailingFPFeatures() const {
    assert(BinaryOperatorBits.HasFPFeatures);
    return reinterpret_cast<const FPOptionsOverride *>(
        reinterpret_cast<const char *>(this) + offsetOfTrailingStorage());
  }

  /// Build a binary operator, assuming that appropriate storage has been
  /// allocated for the trailing objects when needed.
  BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
                 QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
                 SourceLocation opLoc, FPOptionsOverride FPFeatures);

  /// Construct an empty binary operator.
  explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) {
    BinaryOperatorBits.Opc = BO_Comma;
  }

public:
  static BinaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures);

  static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs,
                                Opcode opc, QualType ResTy, ExprValueKind VK,
                                ExprObjectKind OK, SourceLocation opLoc,
                                FPOptionsOverride FPFeatures);
  SourceLocation getExprLoc() const { return getOperatorLoc(); }
  SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; }
  void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; }

  Opcode getOpcode() const {
    return static_cast<Opcode>(BinaryOperatorBits.Opc);
  }
  void setOpcode(Opcode Opc) { BinaryOperatorBits.Opc = Opc; }

  Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
  void setLHS(Expr *E) { SubExprs[LHS] = E; }
  Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
  void setRHS(Expr *E) { SubExprs[RHS] = E; }

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

  /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
  /// corresponds to, e.g. "<<=".
  static StringRef getOpcodeStr(Opcode Op);

  StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); }

  /// Retrieve the binary opcode that corresponds to the given
  /// overloaded operator.
  static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);

  /// Retrieve the overloaded operator kind that corresponds to
  /// the given binary opcode.
  static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);

  /// predicates to categorize the respective opcodes.
  static bool isPtrMemOp(Opcode Opc) {
    return Opc == BO_PtrMemD || Opc == BO_PtrMemI;
  }
  bool isPtrMemOp() const { return isPtrMemOp(getOpcode()); }

  static bool isMultiplicativeOp(Opcode Opc) {
    return Opc >= BO_Mul && Opc <= BO_Rem;
  }
  bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); }
  static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
  bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
  static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
  bool isShiftOp() const { return isShiftOp(getOpcode()); }

  static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
  bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }

  static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
  bool isRelationalOp() const { return isRelationalOp(getOpcode()); }

  static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
  bool isEqualityOp() const { return isEqualityOp(getOpcode()); }

  static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; }
  bool isComparisonOp() const { return isComparisonOp(getOpcode()); }

  static bool isCommaOp(Opcode Opc) { return Opc == BO_Comma; }
  bool isCommaOp() const { return isCommaOp(getOpcode()); }

  static Opcode negateComparisonOp(Opcode Opc) {
    switch (Opc) {
    default:
      llvm_unreachable("Not a comparison operator.");
    case BO_LT: return BO_GE;
    case BO_GT: return BO_LE;
    case BO_LE: return BO_GT;
    case BO_GE: return BO_LT;
    case BO_EQ: return BO_NE;
    case BO_NE: return BO_EQ;
    }
  }

  static Opcode reverseComparisonOp(Opcode Opc) {
    switch (Opc) {
    default:
      llvm_unreachable("Not a comparison operator.");
    case BO_LT: return BO_GT;
    case BO_GT: return BO_LT;
    case BO_LE: return BO_GE;
    case BO_GE: return BO_LE;
    case BO_EQ:
    case BO_NE:
      return Opc;
    }
  }

  static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
  bool isLogicalOp() const { return isLogicalOp(getOpcode()); }

  static bool isAssignmentOp(Opcode Opc) {
    return Opc >= BO_Assign && Opc <= BO_OrAssign;
  }
  bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }

  static bool isCompoundAssignmentOp(Opcode Opc) {
    return Opc > BO_Assign && Opc <= BO_OrAssign;
  }
  bool isCompoundAssignmentOp() const {
    return isCompoundAssignmentOp(getOpcode());
  }
  static Opcode getOpForCompoundAssignment(Opcode Opc) {
    assert(isCompoundAssignmentOp(Opc));
    if (Opc >= BO_AndAssign)
      return Opcode(unsigned(Opc) - BO_AndAssign + BO_And);
    else
      return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul);
  }

  static bool isShiftAssignOp(Opcode Opc) {
    return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
  }
  bool isShiftAssignOp() const {
    return isShiftAssignOp(getOpcode());
  }

  // Return true if a binary operator using the specified opcode and operands
  // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
  // integer to a pointer.
  static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc,
                                               Expr *LHS, Expr *RHS);

  static bool classof(const Stmt *S) {
    return S->getStmtClass() >= firstBinaryOperatorConstant &&
           S->getStmtClass() <= lastBinaryOperatorConstant;
  }

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

  /// Set and fetch the bit that shows whether FPFeatures needs to be
  /// allocated in Trailing Storage
  void setHasStoredFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; }
  bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; }

  /// Get FPFeatures from trailing storage
  FPOptionsOverride getStoredFPFeatures() const {
    assert(hasStoredFPFeatures());
    return *getTrailingFPFeatures();
  }
  /// Set FPFeatures in trailing storage, used only by Serialization
  void setStoredFPFeatures(FPOptionsOverride F) {
    assert(BinaryOperatorBits.HasFPFeatures);
    *getTrailingFPFeatures() = F;
  }

  // Get the FP features status of this operator. Only meaningful for
  // operations on floating point types.
  FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
    if (BinaryOperatorBits.HasFPFeatures)
      return getStoredFPFeatures().applyOverrides(LO);
    return FPOptions::defaultWithoutTrailingStorage(LO);
  }

  // This is used in ASTImporter
  FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
    if (BinaryOperatorBits.HasFPFeatures)
      return getStoredFPFeatures();
    return FPOptionsOverride();
  }

  // Get the FP contractability status of this operator. Only meaningful for
  // operations on floating point types.
  bool isFPContractableWithinStatement(const LangOptions &LO) const {
    return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
  }

  // Get the FENV_ACCESS status of this operator. Only meaningful for
  // operations on floating point types.
  bool isFEnvAccessOn(const LangOptions &LO) const {
    return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
  }

protected:
  BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
                 QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
                 SourceLocation opLoc, FPOptionsOverride FPFeatures,
                 bool dead2);

  /// Construct an empty BinaryOperator, SC is CompoundAssignOperator.
  BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
    BinaryOperatorBits.Opc = BO_MulAssign;
  }

  /// Return the size in bytes needed for the trailing objects.
  /// Used to allocate the right amount of storage.
  static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
    return HasFPFeatures * sizeof(FPOptionsOverride);
  }
};

/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
/// track of the type the operation is performed in.  Due to the semantics of
/// these operators, the operands are promoted, the arithmetic performed, an
/// implicit conversion back to the result type done, then the assignment takes
/// place.  This captures the intermediate type which the computation is done
/// in.
class CompoundAssignOperator : public BinaryOperator {
  QualType ComputationLHSType;
  QualType ComputationResultType;

  /// Construct an empty CompoundAssignOperator.
  explicit CompoundAssignOperator(const ASTContext &C, EmptyShell Empty,
                                  bool hasFPFeatures)
      : BinaryOperator(CompoundAssignOperatorClass, Empty) {}

protected:
  CompoundAssignOperator(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc,
                         QualType ResType, ExprValueKind VK, ExprObjectKind OK,
                         SourceLocation OpLoc, FPOptionsOverride FPFeatures,
                         QualType CompLHSType, QualType CompResultType)
      : BinaryOperator(C, lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
                       true),
        ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) {
    assert(isCompoundAssignmentOp() &&
           "Only should be used for compound assignments");
  }

public:
  static CompoundAssignOperator *CreateEmpty(const ASTContext &C,
                                             bool hasFPFeatures);

  static CompoundAssignOperator *
  Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
         ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
         FPOptionsOverride FPFeatures, QualType CompLHSType = QualType(),
         QualType CompResultType = QualType());

  // The two computation types are the type the LHS is converted
  // to for the computation and the type of the result; the two are
  // distinct in a few cases (specifically, int+=ptr and ptr-=ptr).
  QualType getComputationLHSType() const { return ComputationLHSType; }
  void setComputationLHSType(QualType T) { ComputationLHSType = T; }

  QualType getComputationResultType() const { return ComputationResultType; }
  void setComputationResultType(QualType T) { ComputationResultType = T; }

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

inline size_t BinaryOperator::offsetOfTrailingStorage() const {
  assert(BinaryOperatorBits.HasFPFeatures);
  return isa<CompoundAssignOperator>(this) ? sizeof(CompoundAssignOperator)
                                           : sizeof(BinaryOperator);
}

/// AbstractConditionalOperator - An abstract base class for
/// ConditionalOperator and BinaryConditionalOperator.
class AbstractConditionalOperator : public Expr {
  SourceLocation QuestionLoc, ColonLoc;
  friend class ASTStmtReader;

protected:
  AbstractConditionalOperator(StmtClass SC, QualType T, ExprValueKind VK,
                              ExprObjectKind OK, SourceLocation qloc,
                              SourceLocation cloc)
      : Expr(SC, T, VK, OK), QuestionLoc(qloc), ColonLoc(cloc) {}

  AbstractConditionalOperator(StmtClass SC, EmptyShell Empty)
    : Expr(SC, Empty) { }

public:
  // getCond - Return the expression representing the condition for
  //   the ?: operator.
  Expr *getCond() const;

  // getTrueExpr - Return the subexpression representing the value of
  //   the expression if the condition evaluates to true.
  Expr *getTrueExpr() const;

  // getFalseExpr - Return the subexpression representing the value of
  //   the expression if the condition evaluates to false.  This is
  //   the same as getRHS.
  Expr *getFalseExpr() const;

  SourceLocation getQuestionLoc() const { return QuestionLoc; }
  SourceLocation getColonLoc() const { return ColonLoc; }

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

/// ConditionalOperator - The ?: ternary operator.  The GNU "missing
/// middle" extension is a BinaryConditionalOperator.
class ConditionalOperator : public AbstractConditionalOperator {
  enum { COND, LHS, RHS, END_EXPR };
  Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.

  friend class ASTStmtReader;
public:
  ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
                      SourceLocation CLoc, Expr *rhs, QualType t,
                      ExprValueKind VK, ExprObjectKind OK)
      : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, QLoc,
                                    CLoc) {
    SubExprs[COND] = cond;
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
    setDependence(computeDependence(this));
  }

  /// Build an empty conditional operator.
  explicit ConditionalOperator(EmptyShell Empty)
    : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }

  // getCond - Return the expression representing the condition for
  //   the ?: operator.
  Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }

  // getTrueExpr - Return the subexpression representing the value of
  //   the expression if the condition evaluates to true.
  Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }

  // getFalseExpr - Return the subexpression representing the value of
  //   the expression if the condition evaluates to false.  This is
  //   the same as getRHS.
  Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }

  Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
  Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }

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

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

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

/// BinaryConditionalOperator - The GNU extension to the conditional
/// operator which allows the middle operand to be omitted.
///
/// This is a different expression kind on the assumption that almost
/// every client ends up needing to know that these are different.
class BinaryConditionalOperator : public AbstractConditionalOperator {
  enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS };

  /// - the common condition/left-hand-side expression, which will be
  ///   evaluated as the opaque value
  /// - the condition, expressed in terms of the opaque value
  /// - the left-hand-side, expressed in terms of the opaque value
  /// - the right-hand-side
  Stmt *SubExprs[NUM_SUBEXPRS];
  OpaqueValueExpr *OpaqueValue;

  friend class ASTStmtReader;
public:
  BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue,
                            Expr *cond, Expr *lhs, Expr *rhs,
                            SourceLocation qloc, SourceLocation cloc,
                            QualType t, ExprValueKind VK, ExprObjectKind OK)
      : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK,
                                    qloc, cloc),
        OpaqueValue(opaqueValue) {
    SubExprs[COMMON] = common;
    SubExprs[COND] = cond;
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
    assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
    setDependence(computeDependence(this));
  }

  /// Build an empty conditional operator.
  explicit BinaryConditionalOperator(EmptyShell Empty)
    : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }

  /// getCommon - Return the common expression, written to the
  ///   left of the condition.  The opaque value will be bound to the
  ///   result of this expression.
  Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }

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

  /// getCond - Return the condition expression; this is defined
  ///   in terms of the opaque value.
  Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }

  /// getTrueExpr - Return the subexpression which will be
  ///   evaluated if the condition evaluates to true;  this is defined
  ///   in terms of the opaque value.
  Expr *getTrueExpr() const {
    return cast<Expr>(SubExprs[LHS]);
  }

  /// getFalseExpr - Return the subexpression which will be
  ///   evaluated if the condnition evaluates to false; this is
  ///   defined in terms of the opaque value.
  Expr *getFalseExpr() const {
    return cast<Expr>(SubExprs[RHS]);
  }

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

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

  // Iterators
  child_range children() {
    return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
  }
  const_child_range children() const {
    return const_child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
  }
};

inline Expr *AbstractConditionalOperator::getCond() const {
  if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
    return co->getCond();
  return cast<BinaryConditionalOperator>(this)->getCond();
}

inline Expr *AbstractConditionalOperator::getTrueExpr() const {
  if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
    return co->getTrueExpr();
  return cast<BinaryConditionalOperator>(this)->getTrueExpr();
}

inline Expr *AbstractConditionalOperator::getFalseExpr() const {
  if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
    return co->getFalseExpr();
  return cast<BinaryConditionalOperator>(this)->getFalseExpr();
}

/// AddrLabelExpr - The GNU address of label extension, representing &&label.
class AddrLabelExpr : public Expr {
  SourceLocation AmpAmpLoc, LabelLoc;
  LabelDecl *Label;
public:
  AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
                QualType t)
      : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary), AmpAmpLoc(AALoc),
        LabelLoc(LLoc), Label(L) {
    setDependence(ExprDependence::None);
  }

  /// Build an empty address of a label expression.
  explicit AddrLabelExpr(EmptyShell Empty)
    : Expr(AddrLabelExprClass, Empty) { }

  SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
  void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
  SourceLocation getLabelLoc() const { return LabelLoc; }
  void setLabelLoc(SourceLocation L) { LabelLoc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return AmpAmpLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return LabelLoc; }

  LabelDecl *getLabel() const { return Label; }
  void setLabel(LabelDecl *L) { Label = L; }

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

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

/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
/// takes the value of the last subexpression.
///
/// A StmtExpr is always an r-value; values "returned" out of a
/// StmtExpr will be copied.
class StmtExpr : public Expr {
  Stmt *SubStmt;
  SourceLocation LParenLoc, RParenLoc;
public:
  StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParenLoc,
           SourceLocation RParenLoc, unsigned TemplateDepth)
      : Expr(StmtExprClass, T, VK_RValue, OK_Ordinary), SubStmt(SubStmt),
        LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
    setDependence(computeDependence(this, TemplateDepth));
    // FIXME: A templated statement expression should have an associated
    // DeclContext so that nested declarations always have a dependent context.
    StmtExprBits.TemplateDepth = TemplateDepth;
  }

  /// Build an empty statement expression.
  explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }

  CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); }
  const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
  void setSubStmt(CompoundStmt *S) { SubStmt = S; }

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

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

  unsigned getTemplateDepth() const { return StmtExprBits.TemplateDepth; }

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

  // Iterators
  child_range children() { return child_range(&SubStmt, &SubStmt+1); }
  const_child_range children() const {
    return const_child_range(&SubStmt, &SubStmt + 1);
  }
};

/// ShuffleVectorExpr - clang-specific builtin-in function
/// __builtin_shufflevector.
/// This AST node represents a operator that does a constant
/// shuffle, similar to LLVM's shufflevector instruction. It takes
/// two vectors and a variable number of constant indices,
/// and returns the appropriately shuffled vector.
class ShuffleVectorExpr : public Expr {
  SourceLocation BuiltinLoc, RParenLoc;

  // SubExprs - the list of values passed to the __builtin_shufflevector
  // function. The first two are vectors, and the rest are constant
  // indices.  The number of values in this list is always
  // 2+the number of indices in the vector type.
  Stmt **SubExprs;
  unsigned NumExprs;

public:
  ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
                    SourceLocation BLoc, SourceLocation RP);

  /// Build an empty vector-shuffle expression.
  explicit ShuffleVectorExpr(EmptyShell Empty)
    : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { }

  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
  void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }

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

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

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

  /// getNumSubExprs - Return the size of the SubExprs array.  This includes the
  /// constant expression, the actual arguments passed in, and the function
  /// pointers.
  unsigned getNumSubExprs() const { return NumExprs; }

  /// Retrieve the array of expressions.
  Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }

  /// getExpr - Return the Expr at the specified index.
  Expr *getExpr(unsigned Index) {
    assert((Index < NumExprs) && "Arg access out of range!");
    return cast<Expr>(SubExprs[Index]);
  }
  const Expr *getExpr(unsigned Index) const {
    assert((Index < NumExprs) && "Arg access out of range!");
    return cast<Expr>(SubExprs[Index]);
  }

  void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs);

  llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const {
    assert((N < NumExprs - 2) && "Shuffle idx out of range!");
    return getExpr(N+2)->EvaluateKnownConstInt(Ctx);
  }

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

/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
/// This AST node provides support for converting a vector type to another
/// vector type of the same arity.
class ConvertVectorExpr : public Expr {
private:
  Stmt *SrcExpr;
  TypeSourceInfo *TInfo;
  SourceLocation BuiltinLoc, RParenLoc;

  friend class ASTReader;
  friend class ASTStmtReader;
  explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}

public:
  ConvertVectorExpr(Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType,
                    ExprValueKind VK, ExprObjectKind OK,
                    SourceLocation BuiltinLoc, SourceLocation RParenLoc)
      : Expr(ConvertVectorExprClass, DstType, VK, OK), SrcExpr(SrcExpr),
        TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {
    setDependence(computeDependence(this));
  }

  /// getSrcExpr - Return the Expr to be converted.
  Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }

  /// getTypeSourceInfo - Return the destination type.
  TypeSourceInfo *getTypeSourceInfo() const {
    return TInfo;
  }
  void setTypeSourceInfo(TypeSourceInfo *ti) {
    TInfo = ti;
  }

  /// getBuiltinLoc - Return the location of the __builtin_convertvector token.
  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }

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

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

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

  // Iterators
  child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
  const_child_range children() const {
    return const_child_range(&SrcExpr, &SrcExpr + 1);
  }
};

/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
/// This AST node is similar to the conditional operator (?:) in C, with
/// the following exceptions:
/// - the test expression must be a integer constant expression.
/// - the expression returned acts like the chosen subexpression in every
///   visible way: the type is the same as that of the chosen subexpression,
///   and all predicates (whether it's an l-value, whether it's an integer
///   constant expression, etc.) return the same result as for the chosen
///   sub-expression.
class ChooseExpr : public Expr {
  enum { COND, LHS, RHS, END_EXPR };
  Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
  SourceLocation BuiltinLoc, RParenLoc;
  bool CondIsTrue;
public:
  ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
             ExprValueKind VK, ExprObjectKind OK, SourceLocation RP,
             bool condIsTrue)
      : Expr(ChooseExprClass, t, VK, OK), BuiltinLoc(BLoc), RParenLoc(RP),
        CondIsTrue(condIsTrue) {
    SubExprs[COND] = cond;
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;

    setDependence(computeDependence(this));
  }

  /// Build an empty __builtin_choose_expr.
  explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }

  /// isConditionTrue - Return whether the condition is true (i.e. not
  /// equal to zero).
  bool isConditionTrue() const {
    assert(!isConditionDependent() &&
           "Dependent condition isn't true or false");
    return CondIsTrue;
  }
  void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; }

  bool isConditionDependent() const {
    return getCond()->isTypeDependent() || getCond()->isValueDependent();
  }

  /// getChosenSubExpr - Return the subexpression chosen according to the
  /// condition.
  Expr *getChosenSubExpr() const {
    return isConditionTrue() ? getLHS() : getRHS();
  }

  Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
  void setCond(Expr *E) { SubExprs[COND] = E; }
  Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
  void setLHS(Expr *E) { SubExprs[LHS] = E; }
  Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
  void setRHS(Expr *E) { SubExprs[RHS] = E; }

  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
  void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }

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

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

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

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

/// GNUNullExpr - Implements the GNU __null extension, which is a name
/// for a null pointer constant that has integral type (e.g., int or
/// long) and is the same size and alignment as a pointer. The __null
/// extension is typically only used by system headers, which define
/// NULL as __null in C++ rather than using 0 (which is an integer
/// that may not match the size of a pointer).
class GNUNullExpr : public Expr {
  /// TokenLoc - The location of the __null keyword.
  SourceLocation TokenLoc;

public:
  GNUNullExpr(QualType Ty, SourceLocation Loc)
      : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary), TokenLoc(Loc) {
    setDependence(ExprDependence::None);
  }

  /// Build an empty GNU __null expression.
  explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }

  /// getTokenLocation - The location of the __null token.
  SourceLocation getTokenLocation() const { return TokenLoc; }
  void setTokenLocation(SourceLocation L) { TokenLoc = L; }

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

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

  // 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 call to the builtin function \c __builtin_va_arg.
class VAArgExpr : public Expr {
  Stmt *Val;
  llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo;
  SourceLocation BuiltinLoc, RParenLoc;
public:
  VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo,
            SourceLocation RPLoc, QualType t, bool IsMS)
      : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary), Val(e),
        TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {
    setDependence(computeDependence(this));
  }

  /// Create an empty __builtin_va_arg expression.
  explicit VAArgExpr(EmptyShell Empty)
      : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {}

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

  /// Returns whether this is really a Win64 ABI va_arg expression.
  bool isMicrosoftABI() const { return TInfo.getInt(); }
  void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); }

  TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); }
  void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); }

  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
  void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }

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

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

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

  // Iterators
  child_range children() { return child_range(&Val, &Val+1); }
  const_child_range children() const {
    return const_child_range(&Val, &Val + 1);
  }
};

/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
/// __builtin_FUNCTION(), or __builtin_FILE().
class SourceLocExpr final : public Expr {
  SourceLocation BuiltinLoc, RParenLoc;
  DeclContext *ParentContext;

public:
  enum IdentKind { Function, File, Line, Column };

  SourceLocExpr(const ASTContext &Ctx, IdentKind Type, SourceLocation BLoc,
                SourceLocation RParenLoc, DeclContext *Context);

  /// Build an empty call expression.
  explicit SourceLocExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}

  /// Return the result of evaluating this SourceLocExpr in the specified
  /// (and possibly null) default argument or initialization context.
  APValue EvaluateInContext(const ASTContext &Ctx,
                            const Expr *DefaultExpr) const;

  /// Return a string representing the name of the specific builtin function.
  StringRef getBuiltinStr() const;

  IdentKind getIdentKind() const {
    return static_cast<IdentKind>(SourceLocExprBits.Kind);
  }

  bool isStringType() const {
    switch (getIdentKind()) {
    case File:
    case Function:
      return true;
    case Line:
    case Column:
      return false;
    }
    llvm_unreachable("unknown source location expression kind");
  }
  bool isIntType() const LLVM_READONLY { return !isStringType(); }

  /// If the SourceLocExpr has been resolved return the subexpression
  /// representing the resolved value. Otherwise return null.
  const DeclContext *getParentContext() const { return ParentContext; }
  DeclContext *getParentContext() { return ParentContext; }

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

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

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

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

private:
  friend class ASTStmtReader;
};

/// Describes an C or C++ initializer list.
///
/// InitListExpr describes an initializer list, which can be used to
/// initialize objects of different types, including
/// struct/class/union types, arrays, and vectors. For example:
///
/// @code
/// struct foo x = { 1, { 2, 3 } };
/// @endcode
///
/// Prior to semantic analysis, an initializer list will represent the
/// initializer list as written by the user, but will have the
/// placeholder type "void". This initializer list is called the
/// syntactic form of the initializer, and may contain C99 designated
/// initializers (represented as DesignatedInitExprs), initializations
/// of subobject members without explicit braces, and so on. Clients
/// interested in the original syntax of the initializer list should
/// use the syntactic form of the initializer list.
///
/// After semantic analysis, the initializer list will represent the
/// semantic form of the initializer, where the initializations of all
/// subobjects are made explicit with nested InitListExpr nodes and
/// C99 designators have been eliminated by placing the designated
/// initializations into the subobject they initialize. Additionally,
/// any "holes" in the initialization, where no initializer has been
/// specified for a particular subobject, will be replaced with
/// implicitly-generated ImplicitValueInitExpr expressions that
/// value-initialize the subobjects. Note, however, that the
/// initializer lists may still have fewer initializers than there are
/// elements to initialize within the object.
///
/// After semantic analysis has completed, given an initializer list,
/// method isSemanticForm() returns true if and only if this is the
/// semantic form of the initializer list (note: the same AST node
/// may at the same time be the syntactic form).
/// Given the semantic form of the initializer list, one can retrieve
/// the syntactic form of that initializer list (when different)
/// using method getSyntacticForm(); the method returns null if applied
/// to a initializer list which is already in syntactic form.
/// Similarly, given the syntactic form (i.e., an initializer list such
/// that isSemanticForm() returns false), one can retrieve the semantic
/// form using method getSemanticForm().
/// Since many initializer lists have the same syntactic and semantic forms,
/// getSyntacticForm() may return NULL, indicating that the current
/// semantic initializer list also serves as its syntactic form.
class InitListExpr : public Expr {
  // FIXME: Eliminate this vector in favor of ASTContext allocation
  typedef ASTVector<Stmt *> InitExprsTy;
  InitExprsTy InitExprs;
  SourceLocation LBraceLoc, RBraceLoc;

  /// The alternative form of the initializer list (if it exists).
  /// The int part of the pair stores whether this initializer list is
  /// in semantic form. If not null, the pointer points to:
  ///   - the syntactic form, if this is in semantic form;
  ///   - the semantic form, if this is in syntactic form.
  llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm;

  /// Either:
  ///  If this initializer list initializes an array with more elements than
  ///  there are initializers in the list, specifies an expression to be used
  ///  for value initialization of the rest of the elements.
  /// Or
  ///  If this initializer list initializes a union, specifies which
  ///  field within the union will be initialized.
  llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit;

public:
  InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
               ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);

  /// Build an empty initializer list.
  explicit InitListExpr(EmptyShell Empty)
    : Expr(InitListExprClass, Empty), AltForm(nullptr, true) { }

  unsigned getNumInits() const { return InitExprs.size(); }

  /// Retrieve the set of initializers.
  Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }

  /// Retrieve the set of initializers.
  Expr * const *getInits() const {
    return reinterpret_cast<Expr * const *>(InitExprs.data());
  }

  ArrayRef<Expr *> inits() {
    return llvm::makeArrayRef(getInits(), getNumInits());
  }

  ArrayRef<Expr *> inits() const {
    return llvm::makeArrayRef(getInits(), getNumInits());
  }

  const Expr *getInit(unsigned Init) const {
    assert(Init < getNumInits() && "Initializer access out of range!");
    return cast_or_null<Expr>(InitExprs[Init]);
  }

  Expr *getInit(unsigned Init) {
    assert(Init < getNumInits() && "Initializer access out of range!");
    return cast_or_null<Expr>(InitExprs[Init]);
  }

  void setInit(unsigned Init, Expr *expr) {
    assert(Init < getNumInits() && "Initializer access out of range!");
    InitExprs[Init] = expr;

    if (expr)
      setDependence(getDependence() | expr->getDependence());
  }

  /// Mark the semantic form of the InitListExpr as error when the semantic
  /// analysis fails.
  void markError() {
    assert(isSemanticForm());
    setDependence(getDependence() | ExprDependence::ErrorDependent);
  }

  /// Reserve space for some number of initializers.
  void reserveInits(const ASTContext &C, unsigned NumInits);

  /// Specify the number of initializers
  ///
  /// If there are more than @p NumInits initializers, the remaining
  /// initializers will be destroyed. If there are fewer than @p
  /// NumInits initializers, NULL expressions will be added for the
  /// unknown initializers.
  void resizeInits(const ASTContext &Context, unsigned NumInits);

  /// Updates the initializer at index @p Init with the new
  /// expression @p expr, and returns the old expression at that
  /// location.
  ///
  /// When @p Init is out of range for this initializer list, the
  /// initializer list will be extended with NULL expressions to
  /// accommodate the new entry.
  Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr);

  /// If this initializer list initializes an array with more elements
  /// than there are initializers in the list, specifies an expression to be
  /// used for value initialization of the rest of the elements.
  Expr *getArrayFiller() {
    return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
  }
  const Expr *getArrayFiller() const {
    return const_cast<InitListExpr *>(this)->getArrayFiller();
  }
  void setArrayFiller(Expr *filler);

  /// Return true if this is an array initializer and its array "filler"
  /// has been set.
  bool hasArrayFiller() const { return getArrayFiller(); }

  /// If this initializes a union, specifies which field in the
  /// union to initialize.
  ///
  /// Typically, this field is the first named field within the
  /// union. However, a designated initializer can specify the
  /// initialization of a different field within the union.
  FieldDecl *getInitializedFieldInUnion() {
    return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
  }
  const FieldDecl *getInitializedFieldInUnion() const {
    return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
  }
  void setInitializedFieldInUnion(FieldDecl *FD) {
    assert((FD == nullptr
            || getInitializedFieldInUnion() == nullptr
            || getInitializedFieldInUnion() == FD)
           && "Only one field of a union may be initialized at a time!");
    ArrayFillerOrUnionFieldInit = FD;
  }

  // Explicit InitListExpr's originate from source code (and have valid source
  // locations). Implicit InitListExpr's are created by the semantic analyzer.
  // FIXME: This is wrong; InitListExprs created by semantic analysis have
  // valid source locations too!
  bool isExplicit() const {
    return LBraceLoc.isValid() && RBraceLoc.isValid();
  }

  // Is this an initializer for an array of characters, initialized by a string
  // literal or an @encode?
  bool isStringLiteralInit() const;

  /// Is this a transparent initializer list (that is, an InitListExpr that is
  /// purely syntactic, and whose semantics are that of the sole contained
  /// initializer)?
  bool isTransparent() const;

  /// Is this the zero initializer {0} in a language which considers it
  /// idiomatic?
  bool isIdiomaticZeroInitializer(const LangOptions &LangOpts) const;

  SourceLocation getLBraceLoc() const { return LBraceLoc; }
  void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
  SourceLocation getRBraceLoc() const { return RBraceLoc; }
  void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }

  bool isSemanticForm() const { return AltForm.getInt(); }
  InitListExpr *getSemanticForm() const {
    return isSemanticForm() ? nullptr : AltForm.getPointer();
  }
  bool isSyntacticForm() const {
    return !AltForm.getInt() || !AltForm.getPointer();
  }
  InitListExpr *getSyntacticForm() const {
    return isSemanticForm() ? AltForm.getPointer() : nullptr;
  }

  void setSyntacticForm(InitListExpr *Init) {
    AltForm.setPointer(Init);
    AltForm.setInt(true);
    Init->AltForm.setPointer(this);
    Init->AltForm.setInt(false);
  }

  bool hadArrayRangeDesignator() const {
    return InitListExprBits.HadArrayRangeDesignator != 0;
  }
  void sawArrayRangeDesignator(bool ARD = true) {
    InitListExprBits.HadArrayRangeDesignator = ARD;
  }

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

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

  // Iterators
  child_range children() {
    const_child_range CCR = const_cast<const InitListExpr *>(this)->children();
    return child_range(cast_away_const(CCR.begin()),
                       cast_away_const(CCR.end()));
  }

  const_child_range children() const {
    // FIXME: This does not include the array filler expression.
    if (InitExprs.empty())
      return const_child_range(const_child_iterator(), const_child_iterator());
    return const_child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
  }

  typedef InitExprsTy::iterator iterator;
  typedef InitExprsTy::const_iterator const_iterator;
  typedef InitExprsTy::reverse_iterator reverse_iterator;
  typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;

  iterator begin() { return InitExprs.begin(); }
  const_iterator begin() const { return InitExprs.begin(); }
  iterator end() { return InitExprs.end(); }
  const_iterator end() const { return InitExprs.end(); }
  reverse_iterator rbegin() { return InitExprs.rbegin(); }
  const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
  reverse_iterator rend() { return InitExprs.rend(); }
  const_reverse_iterator rend() const { return InitExprs.rend(); }

  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// Represents a C99 designated initializer expression.
///
/// A designated initializer expression (C99 6.7.8) contains one or
/// more designators (which can be field designators, array
/// designators, or GNU array-range designators) followed by an
/// expression that initializes the field or element(s) that the
/// designators refer to. For example, given:
///
/// @code
/// struct point {
///   double x;
///   double y;
/// };
/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
/// @endcode
///
/// The InitListExpr contains three DesignatedInitExprs, the first of
/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
/// designators, one array designator for @c [2] followed by one field
/// designator for @c .y. The initialization expression will be 1.0.
class DesignatedInitExpr final
    : public Expr,
      private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> {
public:
  /// Forward declaration of the Designator class.
  class Designator;

private:
  /// The location of the '=' or ':' prior to the actual initializer
  /// expression.
  SourceLocation EqualOrColonLoc;

  /// Whether this designated initializer used the GNU deprecated
  /// syntax rather than the C99 '=' syntax.
  unsigned GNUSyntax : 1;

  /// The number of designators in this initializer expression.
  unsigned NumDesignators : 15;

  /// The number of subexpressions of this initializer expression,
  /// which contains both the initializer and any additional
  /// expressions used by array and array-range designators.
  unsigned NumSubExprs : 16;

  /// The designators in this designated initialization
  /// expression.
  Designator *Designators;

  DesignatedInitExpr(const ASTContext &C, QualType Ty,
                     llvm::ArrayRef<Designator> Designators,
                     SourceLocation EqualOrColonLoc, bool GNUSyntax,
                     ArrayRef<Expr *> IndexExprs, Expr *Init);

  explicit DesignatedInitExpr(unsigned NumSubExprs)
    : Expr(DesignatedInitExprClass, EmptyShell()),
      NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { }

public:
  /// A field designator, e.g., ".x".
  struct FieldDesignator {
    /// Refers to the field that is being initialized. The low bit
    /// of this field determines whether this is actually a pointer
    /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When
    /// initially constructed, a field designator will store an
    /// IdentifierInfo*. After semantic analysis has resolved that
    /// name, the field designator will instead store a FieldDecl*.
    uintptr_t NameOrField;

    /// The location of the '.' in the designated initializer.
    SourceLocation DotLoc;

    /// The location of the field name in the designated initializer.
    SourceLocation FieldLoc;
  };

  /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
  struct ArrayOrRangeDesignator {
    /// Location of the first index expression within the designated
    /// initializer expression's list of subexpressions.
    unsigned Index;
    /// The location of the '[' starting the array range designator.
    SourceLocation LBracketLoc;
    /// The location of the ellipsis separating the start and end
    /// indices. Only valid for GNU array-range designators.
    SourceLocation EllipsisLoc;
    /// The location of the ']' terminating the array range designator.
    SourceLocation RBracketLoc;
  };

  /// Represents a single C99 designator.
  ///
  /// @todo This class is infuriatingly similar to clang::Designator,
  /// but minor differences (storing indices vs. storing pointers)
  /// keep us from reusing it. Try harder, later, to rectify these
  /// differences.
  class Designator {
    /// The kind of designator this describes.
    enum {
      FieldDesignator,
      ArrayDesignator,
      ArrayRangeDesignator
    } Kind;

    union {
      /// A field designator, e.g., ".x".
      struct FieldDesignator Field;
      /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
      struct ArrayOrRangeDesignator ArrayOrRange;
    };
    friend class DesignatedInitExpr;

  public:
    Designator() {}

    /// Initializes a field designator.
    Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
               SourceLocation FieldLoc)
      : Kind(FieldDesignator) {
      new (&Field) DesignatedInitExpr::FieldDesignator;
      Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
      Field.DotLoc = DotLoc;
      Field.FieldLoc = FieldLoc;
    }

    /// Initializes an array designator.
    Designator(unsigned Index, SourceLocation LBracketLoc,
               SourceLocation RBracketLoc)
      : Kind(ArrayDesignator) {
      new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator;
      ArrayOrRange.Index = Index;
      ArrayOrRange.LBracketLoc = LBracketLoc;
      ArrayOrRange.EllipsisLoc = SourceLocation();
      ArrayOrRange.RBracketLoc = RBracketLoc;
    }

    /// Initializes a GNU array-range designator.
    Designator(unsigned Index, SourceLocation LBracketLoc,
               SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
      : Kind(ArrayRangeDesignator) {
      new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator;
      ArrayOrRange.Index = Index;
      ArrayOrRange.LBracketLoc = LBracketLoc;
      ArrayOrRange.EllipsisLoc = EllipsisLoc;
      ArrayOrRange.RBracketLoc = RBracketLoc;
    }

    bool isFieldDesignator() const { return Kind == FieldDesignator; }
    bool isArrayDesignator() const { return Kind == ArrayDesignator; }
    bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }

    IdentifierInfo *getFieldName() const;

    FieldDecl *getField() const {
      assert(Kind == FieldDesignator && "Only valid on a field designator");
      if (Field.NameOrField & 0x01)
        return nullptr;
      else
        return reinterpret_cast<FieldDecl *>(Field.NameOrField);
    }

    void setField(FieldDecl *FD) {
      assert(Kind == FieldDesignator && "Only valid on a field designator");
      Field.NameOrField = reinterpret_cast<uintptr_t>(FD);
    }

    SourceLocation getDotLoc() const {
      assert(Kind == FieldDesignator && "Only valid on a field designator");
      return Field.DotLoc;
    }

    SourceLocation getFieldLoc() const {
      assert(Kind == FieldDesignator && "Only valid on a field designator");
      return Field.FieldLoc;
    }

    SourceLocation getLBracketLoc() const {
      assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
             "Only valid on an array or array-range designator");
      return ArrayOrRange.LBracketLoc;
    }

    SourceLocation getRBracketLoc() const {
      assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
             "Only valid on an array or array-range designator");
      return ArrayOrRange.RBracketLoc;
    }

    SourceLocation getEllipsisLoc() const {
      assert(Kind == ArrayRangeDesignator &&
             "Only valid on an array-range designator");
      return ArrayOrRange.EllipsisLoc;
    }

    unsigned getFirstExprIndex() const {
      assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
             "Only valid on an array or array-range designator");
      return ArrayOrRange.Index;
    }

    SourceLocation getBeginLoc() const LLVM_READONLY {
      if (Kind == FieldDesignator)
        return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
      else
        return getLBracketLoc();
    }
    SourceLocation getEndLoc() const LLVM_READONLY {
      return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
    }
    SourceRange getSourceRange() const LLVM_READONLY {
      return SourceRange(getBeginLoc(), getEndLoc());
    }
  };

  static DesignatedInitExpr *Create(const ASTContext &C,
                                    llvm::ArrayRef<Designator> Designators,
                                    ArrayRef<Expr*> IndexExprs,
                                    SourceLocation EqualOrColonLoc,
                                    bool GNUSyntax, Expr *Init);

  static DesignatedInitExpr *CreateEmpty(const ASTContext &C,
                                         unsigned NumIndexExprs);

  /// Returns the number of designators in this initializer.
  unsigned size() const { return NumDesignators; }

  // Iterator access to the designators.
  llvm::MutableArrayRef<Designator> designators() {
    return {Designators, NumDesignators};
  }

  llvm::ArrayRef<Designator> designators() const {
    return {Designators, NumDesignators};
  }

  Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; }
  const Designator *getDesignator(unsigned Idx) const {
    return &designators()[Idx];
  }

  void setDesignators(const ASTContext &C, const Designator *Desigs,
                      unsigned NumDesigs);

  Expr *getArrayIndex(const Designator &D) const;
  Expr *getArrayRangeStart(const Designator &D) const;
  Expr *getArrayRangeEnd(const Designator &D) const;

  /// Retrieve the location of the '=' that precedes the
  /// initializer value itself, if present.
  SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
  void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }

  /// Whether this designated initializer should result in direct-initialization
  /// of the designated subobject (eg, '{.foo{1, 2, 3}}').
  bool isDirectInit() const { return EqualOrColonLoc.isInvalid(); }

  /// Determines whether this designated initializer used the
  /// deprecated GNU syntax for designated initializers.
  bool usesGNUSyntax() const { return GNUSyntax; }
  void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }

  /// Retrieve the initializer value.
  Expr *getInit() const {
    return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
  }

  void setInit(Expr *init) {
    *child_begin() = init;
  }

  /// Retrieve the total number of subexpressions in this
  /// designated initializer expression, including the actual
  /// initialized value and any expressions that occur within array
  /// and array-range designators.
  unsigned getNumSubExprs() const { return NumSubExprs; }

  Expr *getSubExpr(unsigned Idx) const {
    assert(Idx < NumSubExprs && "Subscript out of range");
    return cast<Expr>(getTrailingObjects<Stmt *>()[Idx]);
  }

  void setSubExpr(unsigned Idx, Expr *E) {
    assert(Idx < NumSubExprs && "Subscript out of range");
    getTrailingObjects<Stmt *>()[Idx] = E;
  }

  /// Replaces the designator at index @p Idx with the series
  /// of designators in [First, Last).
  void ExpandDesignator(const ASTContext &C, unsigned Idx,
                        const Designator *First, const Designator *Last);

  SourceRange getDesignatorsSourceRange() const;

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

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

  // Iterators
  child_range children() {
    Stmt **begin = getTrailingObjects<Stmt *>();
    return child_range(begin, begin + NumSubExprs);
  }
  const_child_range children() const {
    Stmt * const *begin = getTrailingObjects<Stmt *>();
    return const_child_range(begin, begin + NumSubExprs);
  }

  friend TrailingObjects;
};

/// Represents a place-holder for an object not to be initialized by
/// anything.
///
/// This only makes sense when it appears as part of an updater of a
/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE
/// initializes a big object, and the NoInitExpr's mark the spots within the
/// big object not to be overwritten by the updater.
///
/// \see DesignatedInitUpdateExpr
class NoInitExpr : public Expr {
public:
  explicit NoInitExpr(QualType ty)
      : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary) {
    setDependence(computeDependence(this));
  }

  explicit NoInitExpr(EmptyShell Empty)
    : Expr(NoInitExprClass, Empty) { }

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

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

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

// In cases like:
//   struct Q { int a, b, c; };
//   Q *getQ();
//   void foo() {
//     struct A { Q q; } a = { *getQ(), .q.b = 3 };
//   }
//
// We will have an InitListExpr for a, with type A, and then a
// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE
// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3"
//
class DesignatedInitUpdateExpr : public Expr {
  // BaseAndUpdaterExprs[0] is the base expression;
  // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base.
  Stmt *BaseAndUpdaterExprs[2];

public:
  DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc,
                           Expr *baseExprs, SourceLocation rBraceLoc);

  explicit DesignatedInitUpdateExpr(EmptyShell Empty)
    : Expr(DesignatedInitUpdateExprClass, Empty) { }

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

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

  Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); }
  void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; }

  InitListExpr *getUpdater() const {
    return cast<InitListExpr>(BaseAndUpdaterExprs[1]);
  }
  void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; }

  // Iterators
  // children = the base and the updater
  child_range children() {
    return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
  }
  const_child_range children() const {
    return const_child_range(&BaseAndUpdaterExprs[0],
                             &BaseAndUpdaterExprs[0] + 2);
  }
};

/// Represents a loop initializing the elements of an array.
///
/// The need to initialize the elements of an array occurs in a number of
/// contexts:
///
///  * in the implicit copy/move constructor for a class with an array member
///  * when a lambda-expression captures an array by value
///  * when a decomposition declaration decomposes an array
///
/// There are two subexpressions: a common expression (the source array)
/// that is evaluated once up-front, and a per-element initializer that
/// runs once for each array element.
///
/// Within the per-element initializer, the common expression may be referenced
/// via an OpaqueValueExpr, and the current index may be obtained via an
/// ArrayInitIndexExpr.
class ArrayInitLoopExpr : public Expr {
  Stmt *SubExprs[2];

  explicit ArrayInitLoopExpr(EmptyShell Empty)
      : Expr(ArrayInitLoopExprClass, Empty), SubExprs{} {}

public:
  explicit ArrayInitLoopExpr(QualType T, Expr *CommonInit, Expr *ElementInit)
      : Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary),
        SubExprs{CommonInit, ElementInit} {
    setDependence(computeDependence(this));
  }

  /// Get the common subexpression shared by all initializations (the source
  /// array).
  OpaqueValueExpr *getCommonExpr() const {
    return cast<OpaqueValueExpr>(SubExprs[0]);
  }

  /// Get the initializer to use for each array element.
  Expr *getSubExpr() const { return cast<Expr>(SubExprs[1]); }

  llvm::APInt getArraySize() const {
    return cast<ConstantArrayType>(getType()->castAsArrayTypeUnsafe())
        ->getSize();
  }

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

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

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

  friend class ASTReader;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// Represents the index of the current element of an array being
/// initialized by an ArrayInitLoopExpr. This can only appear within the
/// subexpression of an ArrayInitLoopExpr.
class ArrayInitIndexExpr : public Expr {
  explicit ArrayInitIndexExpr(EmptyShell Empty)
      : Expr(ArrayInitIndexExprClass, Empty) {}

public:
  explicit ArrayInitIndexExpr(QualType T)
      : Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary) {
    setDependence(ExprDependence::None);
  }

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

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

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

  friend class ASTReader;
  friend class ASTStmtReader;
};

/// Represents an implicitly-generated value initialization of
/// an object of a given type.
///
/// Implicit value initializations occur within semantic initializer
/// list expressions (InitListExpr) as placeholders for subobject
/// initializations not explicitly specified by the user.
///
/// \see InitListExpr
class ImplicitValueInitExpr : public Expr {
public:
  explicit ImplicitValueInitExpr(QualType ty)
      : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary) {
    setDependence(computeDependence(this));
  }

  /// Construct an empty implicit value initialization.
  explicit ImplicitValueInitExpr(EmptyShell Empty)
    : Expr(ImplicitValueInitExprClass, Empty) { }

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

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

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

class ParenListExpr final
    : public Expr,
      private llvm::TrailingObjects<ParenListExpr, Stmt *> {
  friend class ASTStmtReader;
  friend TrailingObjects;

  /// The location of the left and right parentheses.
  SourceLocation LParenLoc, RParenLoc;

  /// Build a paren list.
  ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
                SourceLocation RParenLoc);

  /// Build an empty paren list.
  ParenListExpr(EmptyShell Empty, unsigned NumExprs);

public:
  /// Create a paren list.
  static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc,
                               ArrayRef<Expr *> Exprs,
                               SourceLocation RParenLoc);

  /// Create an empty paren list.
  static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs);

  /// Return the number of expressions in this paren list.
  unsigned getNumExprs() const { return ParenListExprBits.NumExprs; }

  Expr *getExpr(unsigned Init) {
    assert(Init < getNumExprs() && "Initializer access out of range!");
    return getExprs()[Init];
  }

  const Expr *getExpr(unsigned Init) const {
    return const_cast<ParenListExpr *>(this)->getExpr(Init);
  }

  Expr **getExprs() {
    return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
  }

  ArrayRef<Expr *> exprs() {
    return llvm::makeArrayRef(getExprs(), getNumExprs());
  }

  SourceLocation getLParenLoc() const { return LParenLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  SourceLocation getBeginLoc() const { return getLParenLoc(); }
  SourceLocation getEndLoc() const { return getRParenLoc(); }

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

  // Iterators
  child_range children() {
    return child_range(getTrailingObjects<Stmt *>(),
                       getTrailingObjects<Stmt *>() + getNumExprs());
  }
  const_child_range children() const {
    return const_child_range(getTrailingObjects<Stmt *>(),
                             getTrailingObjects<Stmt *>() + getNumExprs());
  }
};

/// Represents a C11 generic selection.
///
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
/// expression, followed by one or more generic associations.  Each generic
/// association specifies a type name and an expression, or "default" and an
/// expression (in which case it is known as a default generic association).
/// The type and value of the generic selection are identical to those of its
/// result expression, which is defined as the expression in the generic
/// association with a type name that is compatible with the type of the
/// controlling expression, or the expression in the default generic association
/// if no types are compatible.  For example:
///
/// @code
/// _Generic(X, double: 1, float: 2, default: 3)
/// @endcode
///
/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f
/// or 3 if "hello".
///
/// As an extension, generic selections are allowed in C++, where the following
/// additional semantics apply:
///
/// Any generic selection whose controlling expression is type-dependent or
/// which names a dependent type in its association list is result-dependent,
/// which means that the choice of result expression is dependent.
/// Result-dependent generic associations are both type- and value-dependent.
class GenericSelectionExpr final
    : public Expr,
      private llvm::TrailingObjects<GenericSelectionExpr, Stmt *,
                                    TypeSourceInfo *> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The number of association expressions and the index of the result
  /// expression in the case where the generic selection expression is not
  /// result-dependent. The result index is equal to ResultDependentIndex
  /// if and only if the generic selection expression is result-dependent.
  unsigned NumAssocs, ResultIndex;
  enum : unsigned {
    ResultDependentIndex = std::numeric_limits<unsigned>::max(),
    ControllingIndex = 0,
    AssocExprStartIndex = 1
  };

  /// The location of the "default" and of the right parenthesis.
  SourceLocation DefaultLoc, RParenLoc;

  // GenericSelectionExpr is followed by several trailing objects.
  // They are (in order):
  //
  // * A single Stmt * for the controlling expression.
  // * An array of getNumAssocs() Stmt * for the association expressions.
  // * An array of getNumAssocs() TypeSourceInfo *, one for each of the
  //   association expressions.
  unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
    // Add one to account for the controlling expression; the remainder
    // are the associated expressions.
    return 1 + getNumAssocs();
  }

  unsigned numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
    return getNumAssocs();
  }

  template <bool Const> class AssociationIteratorTy;
  /// Bundle together an association expression and its TypeSourceInfo.
  /// The Const template parameter is for the const and non-const versions
  /// of AssociationTy.
  template <bool Const> class AssociationTy {
    friend class GenericSelectionExpr;
    template <bool OtherConst> friend class AssociationIteratorTy;
    using ExprPtrTy = std::conditional_t<Const, const Expr *, Expr *>;
    using TSIPtrTy =
        std::conditional_t<Const, const TypeSourceInfo *, TypeSourceInfo *>;
    ExprPtrTy E;
    TSIPtrTy TSI;
    bool Selected;
    AssociationTy(ExprPtrTy E, TSIPtrTy TSI, bool Selected)
        : E(E), TSI(TSI), Selected(Selected) {}

  public:
    ExprPtrTy getAssociationExpr() const { return E; }
    TSIPtrTy getTypeSourceInfo() const { return TSI; }
    QualType getType() const { return TSI ? TSI->getType() : QualType(); }
    bool isSelected() const { return Selected; }
    AssociationTy *operator->() { return this; }
    const AssociationTy *operator->() const { return this; }
  }; // class AssociationTy

  /// Iterator over const and non-const Association objects. The Association
  /// objects are created on the fly when the iterator is dereferenced.
  /// This abstract over how exactly the association expressions and the
  /// corresponding TypeSourceInfo * are stored.
  template <bool Const>
  class AssociationIteratorTy
      : public llvm::iterator_facade_base<
            AssociationIteratorTy<Const>, std::input_iterator_tag,
            AssociationTy<Const>, std::ptrdiff_t, AssociationTy<Const>,
            AssociationTy<Const>> {
    friend class GenericSelectionExpr;
    // FIXME: This iterator could conceptually be a random access iterator, and
    // it would be nice if we could strengthen the iterator category someday.
    // However this iterator does not satisfy two requirements of forward
    // iterators:
    // a) reference = T& or reference = const T&
    // b) If It1 and It2 are both dereferenceable, then It1 == It2 if and only
    //    if *It1 and *It2 are bound to the same objects.
    // An alternative design approach was discussed during review;
    // store an Association object inside the iterator, and return a reference
    // to it when dereferenced. This idea was discarded beacuse of nasty
    // lifetime issues:
    //    AssociationIterator It = ...;
    //    const Association &Assoc = *It++; // Oops, Assoc is dangling.
    using BaseTy = typename AssociationIteratorTy::iterator_facade_base;
    using StmtPtrPtrTy =
        std::conditional_t<Const, const Stmt *const *, Stmt **>;
    using TSIPtrPtrTy = std::conditional_t<Const, const TypeSourceInfo *const *,
                                           TypeSourceInfo **>;
    StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped.
    TSIPtrPtrTy TSI; // Kept in sync with E.
    unsigned Offset = 0, SelectedOffset = 0;
    AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset,
                          unsigned SelectedOffset)
        : E(E), TSI(TSI), Offset(Offset), SelectedOffset(SelectedOffset) {}

  public:
    AssociationIteratorTy() : E(nullptr), TSI(nullptr) {}
    typename BaseTy::reference operator*() const {
      return AssociationTy<Const>(cast<Expr>(*E), *TSI,
                                  Offset == SelectedOffset);
    }
    typename BaseTy::pointer operator->() const { return **this; }
    using BaseTy::operator++;
    AssociationIteratorTy &operator++() {
      ++E;
      ++TSI;
      ++Offset;
      return *this;
    }
    bool operator==(AssociationIteratorTy Other) const { return E == Other.E; }
  }; // class AssociationIterator

  /// Build a non-result-dependent generic selection expression.
  GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
                       Expr *ControllingExpr,
                       ArrayRef<TypeSourceInfo *> AssocTypes,
                       ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
                       SourceLocation RParenLoc,
                       bool ContainsUnexpandedParameterPack,
                       unsigned ResultIndex);

  /// Build a result-dependent generic selection expression.
  GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
                       Expr *ControllingExpr,
                       ArrayRef<TypeSourceInfo *> AssocTypes,
                       ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
                       SourceLocation RParenLoc,
                       bool ContainsUnexpandedParameterPack);

  /// Build an empty generic selection expression for deserialization.
  explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs);

public:
  /// Create a non-result-dependent generic selection expression.
  static GenericSelectionExpr *
  Create(const ASTContext &Context, SourceLocation GenericLoc,
         Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
         ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
         SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack,
         unsigned ResultIndex);

  /// Create a result-dependent generic selection expression.
  static GenericSelectionExpr *
  Create(const ASTContext &Context, SourceLocation GenericLoc,
         Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
         ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
         SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack);

  /// Create an empty generic selection expression for deserialization.
  static GenericSelectionExpr *CreateEmpty(const ASTContext &Context,
                                           unsigned NumAssocs);

  using Association = AssociationTy<false>;
  using ConstAssociation = AssociationTy<true>;
  using AssociationIterator = AssociationIteratorTy<false>;
  using ConstAssociationIterator = AssociationIteratorTy<true>;
  using association_range = llvm::iterator_range<AssociationIterator>;
  using const_association_range =
      llvm::iterator_range<ConstAssociationIterator>;

  /// The number of association expressions.
  unsigned getNumAssocs() const { return NumAssocs; }

  /// The zero-based index of the result expression's generic association in
  /// the generic selection's association list.  Defined only if the
  /// generic selection is not result-dependent.
  unsigned getResultIndex() const {
    assert(!isResultDependent() &&
           "Generic selection is result-dependent but getResultIndex called!");
    return ResultIndex;
  }

  /// Whether this generic selection is result-dependent.
  bool isResultDependent() const { return ResultIndex == ResultDependentIndex; }

  /// Return the controlling expression of this generic selection expression.
  Expr *getControllingExpr() {
    return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
  }
  const Expr *getControllingExpr() const {
    return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
  }

  /// Return the result expression of this controlling expression. Defined if
  /// and only if the generic selection expression is not result-dependent.
  Expr *getResultExpr() {
    return cast<Expr>(
        getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
  }
  const Expr *getResultExpr() const {
    return cast<Expr>(
        getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
  }

  ArrayRef<Expr *> getAssocExprs() const {
    return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() +
                                            AssocExprStartIndex),
            NumAssocs};
  }
  ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
    return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
  }

  /// Return the Ith association expression with its TypeSourceInfo,
  /// bundled together in GenericSelectionExpr::(Const)Association.
  Association getAssociation(unsigned I) {
    assert(I < getNumAssocs() &&
           "Out-of-range index in GenericSelectionExpr::getAssociation!");
    return Association(
        cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
        getTrailingObjects<TypeSourceInfo *>()[I],
        !isResultDependent() && (getResultIndex() == I));
  }
  ConstAssociation getAssociation(unsigned I) const {
    assert(I < getNumAssocs() &&
           "Out-of-range index in GenericSelectionExpr::getAssociation!");
    return ConstAssociation(
        cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
        getTrailingObjects<TypeSourceInfo *>()[I],
        !isResultDependent() && (getResultIndex() == I));
  }

  association_range associations() {
    AssociationIterator Begin(getTrailingObjects<Stmt *>() +
                                  AssocExprStartIndex,
                              getTrailingObjects<TypeSourceInfo *>(),
                              /*Offset=*/0, ResultIndex);
    AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
                            /*Offset=*/NumAssocs, ResultIndex);
    return llvm::make_range(Begin, End);
  }

  const_association_range associations() const {
    ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() +
                                       AssocExprStartIndex,
                                   getTrailingObjects<TypeSourceInfo *>(),
                                   /*Offset=*/0, ResultIndex);
    ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
                                 /*Offset=*/NumAssocs, ResultIndex);
    return llvm::make_range(Begin, End);
  }

  SourceLocation getGenericLoc() const {
    return GenericSelectionExprBits.GenericLoc;
  }
  SourceLocation getDefaultLoc() const { return DefaultLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  SourceLocation getBeginLoc() const { return getGenericLoc(); }
  SourceLocation getEndLoc() const { return getRParenLoc(); }

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

  child_range children() {
    return child_range(getTrailingObjects<Stmt *>(),
                       getTrailingObjects<Stmt *>() +
                           numTrailingObjects(OverloadToken<Stmt *>()));
  }
  const_child_range children() const {
    return const_child_range(getTrailingObjects<Stmt *>(),
                             getTrailingObjects<Stmt *>() +
                                 numTrailingObjects(OverloadToken<Stmt *>()));
  }
};

//===----------------------------------------------------------------------===//
// Clang Extensions
//===----------------------------------------------------------------------===//

/// ExtVectorElementExpr - This represents access to specific elements of a
/// vector, and may occur on the left hand side or right hand side.  For example
/// the following is legal:  "V.xy = V.zw" if V is a 4 element extended vector.
///
/// Note that the base may have either vector or pointer to vector type, just
/// like a struct field reference.
///
class ExtVectorElementExpr : public Expr {
  Stmt *Base;
  IdentifierInfo *Accessor;
  SourceLocation AccessorLoc;
public:
  ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
                       IdentifierInfo &accessor, SourceLocation loc)
      : Expr(ExtVectorElementExprClass, ty, VK,
             (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent)),
        Base(base), Accessor(&accessor), AccessorLoc(loc) {
    setDependence(computeDependence(this));
  }

  /// Build an empty vector element expression.
  explicit ExtVectorElementExpr(EmptyShell Empty)
    : Expr(ExtVectorElementExprClass, Empty) { }

  const Expr *getBase() const { return cast<Expr>(Base); }
  Expr *getBase() { return cast<Expr>(Base); }
  void setBase(Expr *E) { Base = E; }

  IdentifierInfo &getAccessor() const { return *Accessor; }
  void setAccessor(IdentifierInfo *II) { Accessor = II; }

  SourceLocation getAccessorLoc() const { return AccessorLoc; }
  void setAccessorLoc(SourceLocation L) { AccessorLoc = L; }

  /// getNumElements - Get the number of components being selected.
  unsigned getNumElements() const;

  /// containsDuplicateElements - Return true if any element access is
  /// repeated.
  bool containsDuplicateElements() const;

  /// getEncodedElementAccess - Encode the elements accessed into an llvm
  /// aggregate Constant of ConstantInt(s).
  void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const;

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

  /// isArrow - Return true if the base expression is a pointer to vector,
  /// return false if the base expression is a vector.
  bool isArrow() const;

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

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

/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
/// ^{ statement-body }   or   ^(int arg1, float arg2){ statement-body }
class BlockExpr : public Expr {
protected:
  BlockDecl *TheBlock;
public:
  BlockExpr(BlockDecl *BD, QualType ty)
      : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary), TheBlock(BD) {
    setDependence(computeDependence(this));
  }

  /// Build an empty block expression.
  explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }

  const BlockDecl *getBlockDecl() const { return TheBlock; }
  BlockDecl *getBlockDecl() { return TheBlock; }
  void setBlockDecl(BlockDecl *BD) { TheBlock = BD; }

  // Convenience functions for probing the underlying BlockDecl.
  SourceLocation getCaretLocation() const;
  const Stmt *getBody() const;
  Stmt *getBody();

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

  /// getFunctionType - Return the underlying function type for this block.
  const FunctionProtoType *getFunctionType() const;

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

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

/// Copy initialization expr of a __block variable and a boolean flag that
/// indicates whether the expression can throw.
struct BlockVarCopyInit {
  BlockVarCopyInit() = default;
  BlockVarCopyInit(Expr *CopyExpr, bool CanThrow)
      : ExprAndFlag(CopyExpr, CanThrow) {}
  void setExprAndFlag(Expr *CopyExpr, bool CanThrow) {
    ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow);
  }
  Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); }
  bool canThrow() const { return ExprAndFlag.getInt(); }
  llvm::PointerIntPair<Expr *, 1, bool> ExprAndFlag;
};

/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
/// This AST node provides support for reinterpreting a type to another
/// type of the same size.
class AsTypeExpr : public Expr {
private:
  Stmt *SrcExpr;
  SourceLocation BuiltinLoc, RParenLoc;

  friend class ASTReader;
  friend class ASTStmtReader;
  explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {}

public:
  AsTypeExpr(Expr *SrcExpr, QualType DstType, ExprValueKind VK,
             ExprObjectKind OK, SourceLocation BuiltinLoc,
             SourceLocation RParenLoc)
      : Expr(AsTypeExprClass, DstType, VK, OK), SrcExpr(SrcExpr),
        BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {
    setDependence(computeDependence(this));
  }

  /// getSrcExpr - Return the Expr to be converted.
  Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }

  /// getBuiltinLoc - Return the location of the __builtin_astype token.
  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }

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

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

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

  // Iterators
  child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
  const_child_range children() const {
    return const_child_range(&SrcExpr, &SrcExpr + 1);
  }
};

/// PseudoObjectExpr - An expression which accesses a pseudo-object
/// l-value.  A pseudo-object is an abstract object, accesses to which
/// are translated to calls.  The pseudo-object expression has a
/// syntactic form, which shows how the expression was actually
/// written in the source code, and a semantic form, which is a series
/// of expressions to be executed in order which detail how the
/// operation is actually evaluated.  Optionally, one of the semantic
/// forms may also provide a result value for the expression.
///
/// If any of the semantic-form expressions is an OpaqueValueExpr,
/// that OVE is required to have a source expression, and it is bound
/// to the result of that source expression.  Such OVEs may appear
/// only in subsequent semantic-form expressions and as
/// sub-expressions of the syntactic form.
///
/// PseudoObjectExpr should be used only when an operation can be
/// usefully described in terms of fairly simple rewrite rules on
/// objects and functions that are meant to be used by end-developers.
/// For example, under the Itanium ABI, dynamic casts are implemented
/// as a call to a runtime function called __dynamic_cast; using this
/// class to describe that would be inappropriate because that call is
/// not really part of the user-visible semantics, and instead the
/// cast is properly reflected in the AST and IR-generation has been
/// taught to generate the call as necessary.  In contrast, an
/// Objective-C property access is semantically defined to be
/// equivalent to a particular message send, and this is very much
/// part of the user model.  The name of this class encourages this
/// modelling design.
class PseudoObjectExpr final
    : public Expr,
      private llvm::TrailingObjects<PseudoObjectExpr, Expr *> {
  // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.
  // Always at least two, because the first sub-expression is the
  // syntactic form.

  // PseudoObjectExprBits.ResultIndex - The index of the
  // sub-expression holding the result.  0 means the result is void,
  // which is unambiguous because it's the index of the syntactic
  // form.  Note that this is therefore 1 higher than the value passed
  // in to Create, which is an index within the semantic forms.
  // Note also that ASTStmtWriter assumes this encoding.

  Expr **getSubExprsBuffer() { return getTrailingObjects<Expr *>(); }
  const Expr * const *getSubExprsBuffer() const {
    return getTrailingObjects<Expr *>();
  }

  PseudoObjectExpr(QualType type, ExprValueKind VK,
                   Expr *syntactic, ArrayRef<Expr*> semantic,
                   unsigned resultIndex);

  PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs);

  unsigned getNumSubExprs() const {
    return PseudoObjectExprBits.NumSubExprs;
  }

public:
  /// NoResult - A value for the result index indicating that there is
  /// no semantic result.
  enum : unsigned { NoResult = ~0U };

  static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic,
                                  ArrayRef<Expr*> semantic,
                                  unsigned resultIndex);

  static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell,
                                  unsigned numSemanticExprs);

  /// Return the syntactic form of this expression, i.e. the
  /// expression it actually looks like.  Likely to be expressed in
  /// terms of OpaqueValueExprs bound in the semantic form.
  Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; }
  const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; }

  /// Return the index of the result-bearing expression into the semantics
  /// expressions, or PseudoObjectExpr::NoResult if there is none.
  unsigned getResultExprIndex() const {
    if (PseudoObjectExprBits.ResultIndex == 0) return NoResult;
    return PseudoObjectExprBits.ResultIndex - 1;
  }

  /// Return the result-bearing expression, or null if there is none.
  Expr *getResultExpr() {
    if (PseudoObjectExprBits.ResultIndex == 0)
      return nullptr;
    return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];
  }
  const Expr *getResultExpr() const {
    return const_cast<PseudoObjectExpr*>(this)->getResultExpr();
  }

  unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; }

  typedef Expr * const *semantics_iterator;
  typedef const Expr * const *const_semantics_iterator;
  semantics_iterator semantics_begin() {
    return getSubExprsBuffer() + 1;
  }
  const_semantics_iterator semantics_begin() const {
    return getSubExprsBuffer() + 1;
  }
  semantics_iterator semantics_end() {
    return getSubExprsBuffer() + getNumSubExprs();
  }
  const_semantics_iterator semantics_end() const {
    return getSubExprsBuffer() + getNumSubExprs();
  }

  llvm::iterator_range<semantics_iterator> semantics() {
    return llvm::make_range(semantics_begin(), semantics_end());
  }
  llvm::iterator_range<const_semantics_iterator> semantics() const {
    return llvm::make_range(semantics_begin(), semantics_end());
  }

  Expr *getSemanticExpr(unsigned index) {
    assert(index + 1 < getNumSubExprs());
    return getSubExprsBuffer()[index + 1];
  }
  const Expr *getSemanticExpr(unsigned index) const {
    return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index);
  }

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

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

  child_range children() {
    const_child_range CCR =
        const_cast<const PseudoObjectExpr *>(this)->children();
    return child_range(cast_away_const(CCR.begin()),
                       cast_away_const(CCR.end()));
  }
  const_child_range children() const {
    Stmt *const *cs = const_cast<Stmt *const *>(
        reinterpret_cast<const Stmt *const *>(getSubExprsBuffer()));
    return const_child_range(cs, cs + getNumSubExprs());
  }

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

  friend TrailingObjects;
  friend class ASTStmtReader;
};

/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>,
/// and corresponding __opencl_atomic_* for OpenCL 2.0.
/// All of these instructions take one primary pointer, at least one memory
/// order. The instructions for which getScopeModel returns non-null value
/// take one synch scope.
class AtomicExpr : public Expr {
public:
  enum AtomicOp {
#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
#include "clang/Basic/Builtins.def"
    // Avoid trailing comma
    BI_First = 0
  };

private:
  /// Location of sub-expressions.
  /// The location of Scope sub-expression is NumSubExprs - 1, which is
  /// not fixed, therefore is not defined in enum.
  enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR };
  Stmt *SubExprs[END_EXPR + 1];
  unsigned NumSubExprs;
  SourceLocation BuiltinLoc, RParenLoc;
  AtomicOp Op;

  friend class ASTStmtReader;
public:
  AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
             AtomicOp op, SourceLocation RP);

  /// Determine the number of arguments the specified atomic builtin
  /// should have.
  static unsigned getNumSubExprs(AtomicOp Op);

  /// Build an empty AtomicExpr.
  explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }

  Expr *getPtr() const {
    return cast<Expr>(SubExprs[PTR]);
  }
  Expr *getOrder() const {
    return cast<Expr>(SubExprs[ORDER]);
  }
  Expr *getScope() const {
    assert(getScopeModel() && "No scope");
    return cast<Expr>(SubExprs[NumSubExprs - 1]);
  }
  Expr *getVal1() const {
    if (Op == AO__c11_atomic_init || Op == AO__opencl_atomic_init)
      return cast<Expr>(SubExprs[ORDER]);
    assert(NumSubExprs > VAL1);
    return cast<Expr>(SubExprs[VAL1]);
  }
  Expr *getOrderFail() const {
    assert(NumSubExprs > ORDER_FAIL);
    return cast<Expr>(SubExprs[ORDER_FAIL]);
  }
  Expr *getVal2() const {
    if (Op == AO__atomic_exchange)
      return cast<Expr>(SubExprs[ORDER_FAIL]);
    assert(NumSubExprs > VAL2);
    return cast<Expr>(SubExprs[VAL2]);
  }
  Expr *getWeak() const {
    assert(NumSubExprs > WEAK);
    return cast<Expr>(SubExprs[WEAK]);
  }
  QualType getValueType() const;

  AtomicOp getOp() const { return Op; }
  unsigned getNumSubExprs() const { return NumSubExprs; }

  Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
  const Expr * const *getSubExprs() const {
    return reinterpret_cast<Expr * const *>(SubExprs);
  }

  bool isVolatile() const {
    return getPtr()->getType()->getPointeeType().isVolatileQualified();
  }

  bool isCmpXChg() const {
    return getOp() == AO__c11_atomic_compare_exchange_strong ||
           getOp() == AO__c11_atomic_compare_exchange_weak ||
           getOp() == AO__opencl_atomic_compare_exchange_strong ||
           getOp() == AO__opencl_atomic_compare_exchange_weak ||
           getOp() == AO__atomic_compare_exchange ||
           getOp() == AO__atomic_compare_exchange_n;
  }

  bool isOpenCL() const {
    return getOp() >= AO__opencl_atomic_init &&
           getOp() <= AO__opencl_atomic_fetch_max;
  }

  SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }

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

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

  // Iterators
  child_range children() {
    return child_range(SubExprs, SubExprs+NumSubExprs);
  }
  const_child_range children() const {
    return const_child_range(SubExprs, SubExprs + NumSubExprs);
  }

  /// Get atomic scope model for the atomic op code.
  /// \return empty atomic scope model if the atomic op code does not have
  ///   scope operand.
  static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) {
    auto Kind =
        (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
            ? AtomicScopeModelKind::OpenCL
            : AtomicScopeModelKind::None;
    return AtomicScopeModel::create(Kind);
  }

  /// Get atomic scope model.
  /// \return empty atomic scope model if this atomic expression does not have
  ///   scope operand.
  std::unique_ptr<AtomicScopeModel> getScopeModel() const {
    return getScopeModel(getOp());
  }
};

/// TypoExpr - Internal placeholder for expressions where typo correction
/// still needs to be performed and/or an error diagnostic emitted.
class TypoExpr : public Expr {
  // The location for the typo name.
  SourceLocation TypoLoc;

public:
  TypoExpr(QualType T, SourceLocation TypoLoc)
      : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary), TypoLoc(TypoLoc) {
    assert(T->isDependentType() && "TypoExpr given a non-dependent type");
    setDependence(ExprDependence::TypeValueInstantiation |
                  ExprDependence::Error);
  }

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

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

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

};

/// Frontend produces RecoveryExprs on semantic errors that prevent creating
/// other well-formed expressions. E.g. when type-checking of a binary operator
/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose
/// to produce a recovery expression storing left and right operands.
///
/// RecoveryExpr does not have any semantic meaning in C++, it is only useful to
/// preserve expressions in AST that would otherwise be dropped. It captures
/// subexpressions of some expression that we could not construct and source
/// range covered by the expression.
///
/// By default, RecoveryExpr uses dependence-bits to take advantage of existing
/// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved
/// in `decltype(<broken-expr>)` as part of the `DependentDecltypeType`. In
/// addition to that, clang does not report most errors on dependent
/// expressions, so we get rid of bogus errors for free. However, note that
/// unlike other dependent expressions, RecoveryExpr can be produced in
/// non-template contexts.
///
/// We will preserve the type in RecoveryExpr when the type is known, e.g.
/// preserving the return type for a broken non-overloaded function call, a
/// overloaded call where all candidates have the same return type. In this
/// case, the expression is not type-dependent (unless the known type is itself
/// dependent)
///
/// One can also reliably suppress all bogus errors on expressions containing
/// recovery expressions by examining results of Expr::containsErrors().
class RecoveryExpr final : public Expr,
                           private llvm::TrailingObjects<RecoveryExpr, Expr *> {
public:
  static RecoveryExpr *Create(ASTContext &Ctx, QualType T,
                              SourceLocation BeginLoc, SourceLocation EndLoc,
                              ArrayRef<Expr *> SubExprs);
  static RecoveryExpr *CreateEmpty(ASTContext &Ctx, unsigned NumSubExprs);

  ArrayRef<Expr *> subExpressions() {
    auto *B = getTrailingObjects<Expr *>();
    return llvm::makeArrayRef(B, B + NumExprs);
  }

  ArrayRef<const Expr *> subExpressions() const {
    return const_cast<RecoveryExpr *>(this)->subExpressions();
  }

  child_range children() {
    Stmt **B = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
    return child_range(B, B + NumExprs);
  }

  SourceLocation getBeginLoc() const { return BeginLoc; }
  SourceLocation getEndLoc() const { return EndLoc; }

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

private:
  RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc,
               SourceLocation EndLoc, ArrayRef<Expr *> SubExprs);
  RecoveryExpr(EmptyShell Empty, unsigned NumSubExprs)
      : Expr(RecoveryExprClass, Empty), NumExprs(NumSubExprs) {}

  size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumExprs; }

  SourceLocation BeginLoc, EndLoc;
  unsigned NumExprs;
  friend TrailingObjects;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

} // end namespace clang

#endif // LLVM_CLANG_AST_EXPR_H
