//===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  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/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <cctype>

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

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

/// Expr - 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 Stmt {
  QualType TR;

protected:
  Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
       bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
    : Stmt(SC)
  {
    ExprBits.TypeDependent = TD;
    ExprBits.ValueDependent = VD;
    ExprBits.InstantiationDependent = ID;
    ExprBits.ValueKind = VK;
    ExprBits.ObjectKind = OK;
    ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
    setType(T);
  }

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

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 an expression will never 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;
  }

  /// isValueDependent - Determines whether this expression is
  /// value-dependent (C++ [temp.dep.constexpr]). 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 ExprBits.ValueDependent; }

  /// \brief Set whether this expression is value-dependent or not.
  void setValueDependent(bool VD) {
    ExprBits.ValueDependent = VD;
    if (VD)
      ExprBits.InstantiationDependent = true;
  }

  /// isTypeDependent - Determines whether this expression is
  /// type-dependent (C++ [temp.dep.expr]), which means that its type
  /// could change from one template instantiation to the next. 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 ExprBits.TypeDependent; }

  /// \brief Set whether this expression is type-dependent or not.
  void setTypeDependent(bool TD) {
    ExprBits.TypeDependent = TD;
    if (TD)
      ExprBits.InstantiationDependent = true;
  }

  /// \brief 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.
  ///
  /// 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
  ///
  bool isInstantiationDependent() const {
    return ExprBits.InstantiationDependent;
  }

  /// \brief Set whether this expression is instantiation-dependent or not.
  void setInstantiationDependent(bool ID) {
    ExprBits.InstantiationDependent = ID;
  }

  /// \brief Whether this expression contains an unexpanded parameter
  /// pack (for C++0x 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 ExprBits.ContainsUnexpandedParameterPack;
  }

  /// \brief Set the bit that describes whether this expression
  /// contains an unexpanded parameter pack.
  void setContainsUnexpandedParameterPack(bool PP = true) {
    ExprBits.ContainsUnexpandedParameterPack = PP;
  }

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

  /// isUnusedResultAWarning - Return true if this immediate expression should
  /// be warned about if the result is unused.  If so, fill in Loc and Ranges
  /// with location to warn on and the source range[s] to report with the
  /// warning.
  bool isUnusedResultAWarning(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++0x 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
  };
  /// Reasons why an expression might not be an l-value.
  LValueClassification ClassifyLValue(ASTContext &Ctx) const;

  /// 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.
  enum isModifiableLvalueResult {
    MLV_Valid,
    MLV_NotObjectType,
    MLV_IncompleteVoidType,
    MLV_DuplicateVectorComponents,
    MLV_InvalidExpression,
    MLV_LValueCast,           // Specialized form of MLV_InvalidExpression.
    MLV_IncompleteType,
    MLV_ConstQualified,
    MLV_ArrayType,
    MLV_NotBlockQualified,
    MLV_ReadonlyProperty,
    MLV_NoSetterProperty,
    MLV_MemberFunction,
    MLV_SubObjCPropertySetting,
    MLV_InvalidMessageExpression,
    MLV_ClassTemporary
  };
  isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
                                              SourceLocation *Loc = 0) const;

  /// \brief The return type of classify(). Represents the C++0x expression
  ///        taxonomy.
  class Classification {
  public:
    /// \brief 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 prvalue of class type
      CL_ObjCMessageRValue, // ObjC message is an rvalue
      CL_PRValue // A prvalue for any other reason, of any other type
    };
    /// \brief 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_NotBlockQualified, // Not captured in the closure
      CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
      CM_ConstQualified,
      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; }

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

  };
  /// \brief Classify - Classify this expression according to the C++0x
  ///        expression taxonomy.
  ///
  /// C++0x 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, 0);
  }

  /// \brief ClassifyModifiable - Classify this expression according to the
  ///        C++0x 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);
  }

  /// 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:

  /// \brief If this expression refers to a bit-field, retrieve the
  /// declaration of that bit-field.
  FieldDecl *getBitField();

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

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

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

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

  /// \brief 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.
  bool isKnownToHaveBooleanValue() const;

  /// isIntegerConstantExpr - Return true if this expression is a valid integer
  /// constant expression, and, if so, return its value in Result.  If not a
  /// valid i-c-e, return false 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.
  bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
                             SourceLocation *Loc = 0,
                             bool isEvaluated = true) const;
  bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const;

  /// isCXX98IntegralConstantExpr - Return true if this expression is an
  /// integral constant expression in C++98. Can only be used in C++.
  bool isCXX98IntegralConstantExpr(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(ASTContext &Ctx, APValue *Result = 0,
                           SourceLocation *Loc = 0) 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,
                                      llvm::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.
  bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;

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

    /// 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.
    llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag;

    EvalStatus() : HasSideEffects(false), Diag(0) {}

    // 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) const;

  /// EvaluateAsBooleanCondition - Return true if this is a constant
  /// which we 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) const;

  enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };

  /// 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(llvm::APSInt &Result, const ASTContext &Ctx,
                     SideEffectsKind AllowSideEffects = SE_NoSideEffects) 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) const;

  /// HasSideEffects - This routine returns true for all those expressions
  /// which must be evaluated each time and must not be optimized away
  /// or evaluated at compile time. Example is a function call, volatile
  /// variable read.
  bool HasSideEffects(const ASTContext &Ctx) const;

  /// \brief Determine whether this expression involves a call to any function
  /// that is not trivial.
  bool hasNonTrivialCall(ASTContext &Ctx);
  
  /// 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) 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) 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,
                       llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

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

    /// \brief Expression is a Null pointer constant built from a zero integer.
    NPCK_ZeroInteger,

    /// \brief Expression is a C++0X nullptr.
    NPCK_CXX0X_nullptr,

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

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

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

    /// \brief 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;

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

  /// \brief 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);

  /// \brief Result type of CanThrow().
  enum CanThrowResult {
    CT_Cannot,
    CT_Dependent,
    CT_Can
  };
  /// \brief Test if this expression, if evaluated, might throw, according to
  ///        the rules of C++ [expr.unary.noexcept].
  CanThrowResult CanThrow(ASTContext &C) const;

  /// IgnoreImpCasts - Skip past any implicit casts which might
  /// surround this expression.  Only skips ImplicitCastExprs.
  Expr *IgnoreImpCasts();

  /// IgnoreImplicit - Skip past any implicit AST nodes which might
  /// surround this expression.
  Expr *IgnoreImplicit() { return cast<Expr>(Stmt::IgnoreImplicit()); }

  /// IgnoreParens - Ignore parentheses.  If this Expr is a ParenExpr, return
  ///  its subexpression.  If that subexpression is also a ParenExpr,
  ///  then this method recursively returns its subexpression, and so forth.
  ///  Otherwise, the method returns the current Expr.
  Expr *IgnoreParens();

  /// IgnoreParenCasts - Ignore parentheses and casts.  Strip off any ParenExpr
  /// or CastExprs, returning their operand.
  Expr *IgnoreParenCasts();

  /// IgnoreParenImpCasts - Ignore parentheses and implicit casts.  Strip off
  /// any ParenExpr or ImplicitCastExprs, returning their operand.
  Expr *IgnoreParenImpCasts();

  /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
  /// call to a conversion operator, return the argument.
  Expr *IgnoreConversionOperator();

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

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

  /// Ignore parentheses and lvalue casts.  Strip off any ParenExpr and
  /// CastExprs that represent lvalue casts, returning their operand.
  Expr *IgnoreParenLValueCasts();

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

  /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
  /// value (including ptr->int casts of the same size).  Strip off any
  /// ParenExpr or CastExprs, returning their operand.
  Expr *IgnoreParenNoopCasts(ASTContext &Ctx);

  /// \brief 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;

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

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

  const Expr *IgnoreImpCasts() const {
    return const_cast<Expr*>(this)->IgnoreImpCasts();
  }
  const Expr *IgnoreParens() const {
    return const_cast<Expr*>(this)->IgnoreParens();
  }
  const Expr *IgnoreParenCasts() const {
    return const_cast<Expr*>(this)->IgnoreParenCasts();
  }
  const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const {
    return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
  }

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

  static bool classof(const Stmt *T) {
    return T->getStmtClass() >= firstExprConstant &&
           T->getStmtClass() <= lastExprConstant;
  }
  static bool classof(const Expr *) { return true; }
};


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

public:
  OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
                  ExprObjectKind OK = OK_Ordinary,
                  Expr *SourceExpr = 0)
    : Expr(OpaqueValueExprClass, T, VK, OK,
           T->isDependentType(), 
           T->isDependentType() || 
           (SourceExpr && SourceExpr->isValueDependent()),
           T->isInstantiationDependentType(),
           false),
      SourceExpr(SourceExpr), Loc(Loc) {
  }

  /// 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) { }

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

  SourceRange getSourceRange() const {
    if (SourceExpr) return SourceExpr->getSourceRange();
    return Loc;
  }
  SourceLocation getExprLoc() const {
    if (SourceExpr) return SourceExpr->getExprLoc();
    return Loc;
  }

  child_range children() { return child_range(); }

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

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

/// \brief 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.
class DeclRefExpr : public Expr {
  /// \brief The declaration that we are referencing.
  ValueDecl *D;

  /// \brief The location of the declaration name itself.
  SourceLocation Loc;

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

  /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
  NestedNameSpecifierLoc &getInternalQualifierLoc() {
    assert(hasQualifier());
    return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1);
  }

  /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
  const NestedNameSpecifierLoc &getInternalQualifierLoc() const {
    return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc();
  }

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

  /// \brief Helper to retrieve the optional NamedDecl through which this
  /// reference occured.
  NamedDecl *&getInternalFoundDecl() {
    assert(hasFoundDecl());
    if (hasQualifier())
      return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1);
    return *reinterpret_cast<NamedDecl **>(this + 1);
  }

  /// \brief Helper to retrieve the optional NamedDecl through which this
  /// reference occured.
  NamedDecl *getInternalFoundDecl() const {
    return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
  }

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

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

  /// \brief Computes the type- and value-dependence flags for this
  /// declaration reference expression.
  void computeDependence();

public:
  DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L,
              const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
    : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
      D(D), Loc(L), DNLoc(LocInfo) {
    DeclRefExprBits.HasQualifier = 0;
    DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
    DeclRefExprBits.HasFoundDecl = 0;
    DeclRefExprBits.HadMultipleCandidates = 0;
    computeDependence();
  }

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

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

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

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

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

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

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

  /// \brief If the name was qualified, retrieves the nested-name-specifier
  /// that precedes the name. Otherwise, returns NULL.
  NestedNameSpecifier *getQualifier() const {
    if (!hasQualifier())
      return 0;

    return getInternalQualifierLoc().getNestedNameSpecifier();
  }

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

  /// \brief Get the NamedDecl through which this reference occured.
  ///
  /// 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() ? getInternalFoundDecl() : D;
  }

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

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

  /// \brief Return the optional template keyword and arguments info.
  ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
    if (!hasTemplateKWAndArgsInfo())
      return 0;

    if (hasFoundDecl())
      return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
        &getInternalFoundDecl() + 1);

    if (hasQualifier())
      return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
        &getInternalQualifierLoc() + 1);

    return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
  }

  /// \brief Return the optional template keyword and arguments info.
  const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
    return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo();
  }

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

  /// \brief 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 getTemplateKWAndArgsInfo()->LAngleLoc;
  }

  /// \brief 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 getTemplateKWAndArgsInfo()->RAngleLoc;
  }

  /// \brief Determines whether the name in this declaration reference
  /// was preceded by the template keyword.
  bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

  /// \brief Determines whether this declaration reference was followed by an
  /// explicit template argument list.
  bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }

  /// \brief Retrieve the explicit template argument list that followed the
  /// member template name.
  ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
    assert(hasExplicitTemplateArgs());
    return *getTemplateKWAndArgsInfo();
  }

  /// \brief Retrieve the explicit template argument list that followed the
  /// member template name.
  const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
    return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
  }

  /// \brief Retrieves the optional explicit template arguments.
  /// This points to the same data as getExplicitTemplateArgs(), but
  /// returns null if there are no explicit template arguments.
  const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
    if (!hasExplicitTemplateArgs()) return 0;
    return &getExplicitTemplateArgs();
  }

  /// \brief Copies the template arguments (if present) into the given
  /// structure.
  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
    if (hasExplicitTemplateArgs())
      getExplicitTemplateArgs().copyInto(List);
  }

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

    return getExplicitTemplateArgs().getTemplateArgs();
  }

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

    return getExplicitTemplateArgs().NumTemplateArgs;
  }

  /// \brief 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;
  }
  /// \brief 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;
  }

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

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

  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
public:
  enum IdentType {
    Func,
    Function,
    PrettyFunction,
    /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
    /// 'virtual' keyword is omitted for virtual member functions.
    PrettyFunctionNoVirtual
  };

private:
  SourceLocation Loc;
  IdentType Type;
public:
  PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
    : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
           type->isDependentType(), type->isDependentType(),
           type->isInstantiationDependentType(),
           /*ContainsUnexpandedParameterPack=*/false),
      Loc(l), Type(IT) {}

  /// \brief Construct an empty predefined expression.
  explicit PredefinedExpr(EmptyShell Empty)
    : Expr(PredefinedExprClass, Empty) { }

  IdentType getIdentType() const { return Type; }
  void setIdentType(IdentType IT) { Type = IT; }

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

  static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);

  SourceRange getSourceRange() const { return SourceRange(Loc); }

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

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

/// \brief 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&); // do not implement
  APNumericStorage& operator=(const APNumericStorage&); // do not implement

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(ASTContext &C, const llvm::APInt &Val);
};

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

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

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

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

public:
  // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
  // or UnsignedLongLongTy
  IntegerLiteral(ASTContext &C, const llvm::APInt &V,
                 QualType type, SourceLocation l)
    : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
           false, false),
      Loc(l) {
    assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
    assert(V.getBitWidth() == C.getIntWidth(type) &&
           "Integer type is not the correct size for constant.");
    setValue(C, V);
  }

  /// \brief 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(ASTContext &C, const llvm::APInt &V,
                                QualType type, SourceLocation l);
  /// \brief Returns a new empty integer literal.
  static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);

  SourceRange getSourceRange() const { return SourceRange(Loc); }

  /// \brief 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;
  }
  static bool classof(const IntegerLiteral *) { return true; }

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

class CharacterLiteral : public Expr {
public:
  enum CharacterKind {
    Ascii,
    Wide,
    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, false, false,
           false, false),
      Value(value), Loc(l) {
    CharacterLiteralBits.Kind = kind;
  }

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

  SourceRange getSourceRange() const { return SourceRange(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;
  }
  static bool classof(const CharacterLiteral *) { return true; }

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

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

  FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
                  QualType Type, SourceLocation L)
    : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
           false, false), Loc(L) {
    FloatingLiteralBits.IsIEEE =
      &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
    FloatingLiteralBits.IsExact = isexact;
    setValue(C, V);
  }

  /// \brief Construct an empty floating-point literal.
  explicit FloatingLiteral(ASTContext &C, EmptyShell Empty)
    : Expr(FloatingLiteralClass, Empty) {
    FloatingLiteralBits.IsIEEE =
      &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
    FloatingLiteralBits.IsExact = false;
  }

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

  llvm::APFloat getValue() const {
    return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE);
  }
  void setValue(ASTContext &C, const llvm::APFloat &Val) {
    APFloatStorage::setValue(C, Val);
  }

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

  SourceRange getSourceRange() const { return SourceRange(Loc); }

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

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

/// 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, false, false,
           false, false),
      Val(val) {}

  /// \brief 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; }

  SourceRange getSourceRange() const { return Val->getSourceRange(); }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ImaginaryLiteralClass;
  }
  static bool classof(const ImaginaryLiteral *) { return true; }

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

/// StringLiteral - This represents a string literal expression, e.g. "foo"
/// or L"bar" (wide strings).  The actual string is returned by getStrData()
/// is NOT null-terminated, and the length of the string 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 : public Expr {
public:
  enum StringKind {
    Ascii,
    Wide,
    UTF8,
    UTF16,
    UTF32
  };

private:
  friend class ASTStmtReader;

  union {
    const char *asChar;
    const uint16_t *asUInt16;
    const uint32_t *asUInt32;
  } StrData;
  unsigned Length;
  unsigned CharByteWidth : 4;
  unsigned Kind : 3;
  unsigned IsPascal : 1;
  unsigned NumConcatenated;
  SourceLocation TokLocs[1];

  StringLiteral(QualType Ty) :
    Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
         false) {}

  static int mapCharByteWidth(TargetInfo const &target,StringKind k);

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

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

  /// \brief Construct an empty string literal.
  static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);

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

  /// Allow clients that need the byte representation, such as ASTWriterStmt
  /// ::VisitStringLiteral(), access.
  StringRef getBytes() const {
    // FIXME: StringRef may not be the right type to use as a result for this.
    if (CharByteWidth == 1)
      return StringRef(StrData.asChar, getByteLength());
    if (CharByteWidth == 4)
      return StringRef(reinterpret_cast<const char*>(StrData.asUInt32),
                       getByteLength());
    assert(CharByteWidth == 2 && "unsupported CharByteWidth");
    return StringRef(reinterpret_cast<const char*>(StrData.asUInt16),
                     getByteLength());
  }

  uint32_t getCodeUnit(size_t i) const {
    assert(i < Length && "out of bounds access");
    if (CharByteWidth == 1)
      return static_cast<unsigned char>(StrData.asChar[i]);
    if (CharByteWidth == 4)
      return StrData.asUInt32[i];
    assert(CharByteWidth == 2 && "unsupported CharByteWidth");
    return StrData.asUInt16[i];
  }

  unsigned getByteLength() const { return CharByteWidth*Length; }
  unsigned getLength() const { return Length; }
  unsigned getCharByteWidth() const { return CharByteWidth; }

  /// \brief Sets the string data to the given string data.
  void setString(ASTContext &C, StringRef Str,
                 StringKind Kind, bool IsPascal);

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


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

  bool containsNonAsciiOrNull() const {
    StringRef Str = getString();
    for (unsigned i = 0, e = Str.size(); i != e; ++i)
      if (!isascii(Str[i]) || !Str[i])
        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 NumConcatenated; }

  SourceLocation getStrTokenLoc(unsigned TokNum) const {
    assert(TokNum < NumConcatenated && "Invalid tok number");
    return TokLocs[TokNum];
  }
  void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
    assert(TokNum < NumConcatenated && "Invalid tok number");
    TokLocs[TokNum] = L;
  }

  /// 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) const;

  typedef const SourceLocation *tokloc_iterator;
  tokloc_iterator tokloc_begin() const { return TokLocs; }
  tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }

  SourceRange getSourceRange() const {
    return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == StringLiteralClass;
  }
  static bool classof(const StringLiteral *) { return true; }

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

/// 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(),
           val->isTypeDependent(), val->isValueDependent(),
           val->isInstantiationDependent(),
           val->containsUnexpandedParameterPack()),
      L(l), R(r), Val(val) {}

  /// \brief 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; }

  SourceRange getSourceRange() const { return SourceRange(L, R); }

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

  /// \brief 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;
  }
  static bool classof(const ParenExpr *) { return true; }

  // Iterators
  child_range children() { return 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 : public Expr {
public:
  typedef UnaryOperatorKind Opcode;

private:
  unsigned Opc : 5;
  SourceLocation Loc;
  Stmt *Val;
public:

  UnaryOperator(Expr *input, Opcode opc, QualType type,
                ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
    : Expr(UnaryOperatorClass, type, VK, OK,
           input->isTypeDependent() || type->isDependentType(),
           input->isValueDependent(),
           (input->isInstantiationDependent() ||
            type->isInstantiationDependentType()),
           input->containsUnexpandedParameterPack()),
      Opc(opc), Loc(l), Val(input) {}

  /// \brief Build an empty unary operator.
  explicit UnaryOperator(EmptyShell Empty)
    : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }

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

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

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

  /// 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 const char *getOpcodeStr(Opcode Op);

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

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

  SourceRange getSourceRange() const {
    if (isPostfix())
      return SourceRange(Val->getLocStart(), Loc);
    else
      return SourceRange(Loc, Val->getLocEnd());
  }
  SourceLocation getExprLoc() const { return Loc; }

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

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

/// 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 : public Expr {
public:
  // __builtin_offsetof(type, identifier(.identifier|[expr])*)
  class OffsetOfNode {
  public:
    /// \brief The kind of offsetof node we have.
    enum Kind {
      /// \brief An index into an array.
      Array = 0x00,
      /// \brief A field.
      Field = 0x01,
      /// \brief A field in a dependent type, known only by its name.
      Identifier = 0x02,
      /// \brief 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 };

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

    /// \brief 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:
    /// \brief Create an offsetof node that refers to an array element.
    OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
                 SourceLocation RBracketLoc)
      : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }

    /// \brief 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) { }

    /// \brief 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) { }

    /// \brief 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) {}

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

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

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

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

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

    /// \brief 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 { return Range; }
  };

private:

  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;

  OffsetOfExpr(ASTContext &C, QualType type,
               SourceLocation OperatorLoc, TypeSourceInfo *tsi,
               OffsetOfNode* compsPtr, unsigned numComps,
               Expr** exprsPtr, unsigned numExprs,
               SourceLocation RParenLoc);

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

public:

  static OffsetOfExpr *Create(ASTContext &C, QualType type,
                              SourceLocation OperatorLoc, TypeSourceInfo *tsi,
                              OffsetOfNode* compsPtr, unsigned numComps,
                              Expr** exprsPtr, unsigned numExprs,
                              SourceLocation RParenLoc);

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

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

  /// \brief 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 reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
  }

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

  unsigned getNumComponents() const {
    return NumComps;
  }

  Expr* getIndexExpr(unsigned Idx) {
    assert(Idx < NumExprs && "Subscript out of range");
    return reinterpret_cast<Expr **>(
                    reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
  }
  const Expr *getIndexExpr(unsigned Idx) const {
    return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
  }

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

  unsigned getNumExpressions() const {
    return NumExprs;
  }

  SourceRange getSourceRange() const {
    return SourceRange(OperatorLoc, RParenLoc);
  }

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

  static bool classof(const OffsetOfExpr *) { return true; }

  // Iterators
  child_range children() {
    Stmt **begin =
      reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
                               + NumComps);
    return child_range(begin, begin + NumExprs);
  }
};

/// 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,
           false, // Never type-dependent (C++ [temp.dep.expr]p3).
           // Value-dependent if the argument is type-dependent.
           TInfo->getType()->isDependentType(),
           TInfo->getType()->isInstantiationDependentType(),
           TInfo->getType()->containsUnexpandedParameterPack()),
      OpLoc(op), RParenLoc(rp) {
    UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
    UnaryExprOrTypeTraitExprBits.IsType = true;
    Argument.Ty = TInfo;
  }

  UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
                           QualType resultType, SourceLocation op,
                           SourceLocation rp) :
      Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
           false, // Never type-dependent (C++ [temp.dep.expr]p3).
           // Value-dependent if the argument is type-dependent.
           E->isTypeDependent(),
           E->isInstantiationDependent(),
           E->containsUnexpandedParameterPack()),
      OpLoc(op), RParenLoc(rp) {
    UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
    UnaryExprOrTypeTraitExprBits.IsType = false;
    Argument.Ex = E;
  }

  /// \brief 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) { UnaryExprOrTypeTraitExprBits.Kind = K;}

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

  SourceRange getSourceRange() const {
    return SourceRange(OpLoc, RParenLoc);
  }

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

  // Iterators
  child_range children();
};

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

/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
  enum { LHS, RHS, END_EXPR=2 };
  Stmt* SubExprs[END_EXPR];
  SourceLocation RBracketLoc;
public:
  ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
                     ExprValueKind VK, ExprObjectKind OK,
                     SourceLocation rbracketloc)
  : Expr(ArraySubscriptExprClass, t, VK, OK,
         lhs->isTypeDependent() || rhs->isTypeDependent(),
         lhs->isValueDependent() || rhs->isValueDependent(),
         (lhs->isInstantiationDependent() ||
          rhs->isInstantiationDependent()),
         (lhs->containsUnexpandedParameterPack() ||
          rhs->containsUnexpandedParameterPack())),
    RBracketLoc(rbracketloc) {
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
  }

  /// \brief 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 cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
  }

  const Expr *getBase() const {
    return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
  }

  Expr *getIdx() {
    return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
  }

  const Expr *getIdx() const {
    return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
  }

  SourceRange getSourceRange() const {
    return SourceRange(getLHS()->getLocStart(), RBracketLoc);
  }

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

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

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

  // Iterators
  child_range children() {
    return 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 };
  Stmt **SubExprs;
  unsigned NumArgs;
  SourceLocation RParenLoc;

protected:
  // These versions of the constructor are for derived classes.
  CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
           Expr **args, unsigned numargs, QualType t, ExprValueKind VK,
           SourceLocation rparenloc);
  CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty);

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

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

public:
  CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
           ExprValueKind VK, SourceLocation rparenloc);

  /// \brief Build an empty call expression.
  CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);

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

  Decl *getCalleeDecl();
  const Decl *getCalleeDecl() const {
    return const_cast<CallExpr*>(this)->getCalleeDecl();
  }

  /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
  FunctionDecl *getDirectCallee();
  const FunctionDecl *getDirectCallee() const {
    return const_cast<CallExpr*>(this)->getDirectCallee();
  }

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

  /// \brief Retrieve the call arguments.
  Expr **getArgs() {
    return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
  }
  const Expr *const *getArgs() const {
    return const_cast<CallExpr*>(this)->getArgs();
  }

  /// getArg - Return the specified argument.
  Expr *getArg(unsigned Arg) {
    assert(Arg < NumArgs && "Arg access out of range!");
    return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
  }
  const Expr *getArg(unsigned Arg) const {
    assert(Arg < NumArgs && "Arg access out of range!");
    return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
  }

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

  /// setNumArgs - This changes the number of arguments present in this call.
  /// Any orphaned expressions are deleted by this, and any new operands are set
  /// to null.
  void setNumArgs(ASTContext& C, unsigned NumArgs);

  typedef ExprIterator arg_iterator;
  typedef ConstExprIterator const_arg_iterator;

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

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

  /// isBuiltinCall - If this is a call to a builtin, return the builtin ID.  If
  /// not, return 0.
  unsigned isBuiltinCall() 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;

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

  SourceRange getSourceRange() const;

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

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

/// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
///
class MemberExpr : public Expr {
  /// Extra data stored in some member expressions.
  struct MemberNameQualifier {
    /// \brief The nested-name-specifier that qualifies the name, including
    /// source-location information.
    NestedNameSpecifierLoc QualifierLoc;

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

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

  /// IsArrow - True if this is "X->F", false if this is "X.F".
  bool IsArrow : 1;

  /// \brief True if this member expression used a nested-name-specifier to
  /// refer to the member, e.g., "x->Base::f", or found its member via a using
  /// declaration.  When true, a MemberNameQualifier
  /// structure is allocated immediately after the MemberExpr.
  bool HasQualifierOrFoundDecl : 1;

  /// \brief True if this member expression specified a template keyword
  /// and/or a template argument list explicitly, e.g., x->f<int>,
  /// x->template f, x->template f<int>.
  /// When true, an ASTTemplateKWAndArgsInfo structure and its
  /// TemplateArguments (if any) are allocated immediately after
  /// the MemberExpr or, if the member expression also has a qualifier,
  /// after the MemberNameQualifier structure.
  bool HasTemplateKWAndArgsInfo : 1;

  /// \brief True if this member expression refers to a method that
  /// was resolved from an overloaded set having size greater than 1.
  bool HadMultipleCandidates : 1;

  /// \brief Retrieve the qualifier that preceded the member name, if any.
  MemberNameQualifier *getMemberQualifier() {
    assert(HasQualifierOrFoundDecl);
    return reinterpret_cast<MemberNameQualifier *> (this + 1);
  }

  /// \brief Retrieve the qualifier that preceded the member name, if any.
  const MemberNameQualifier *getMemberQualifier() const {
    return const_cast<MemberExpr *>(this)->getMemberQualifier();
  }

public:
  MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
             const DeclarationNameInfo &NameInfo, QualType ty,
             ExprValueKind VK, ExprObjectKind OK)
    : Expr(MemberExprClass, ty, VK, OK,
           base->isTypeDependent(),
           base->isValueDependent(),
           base->isInstantiationDependent(),
           base->containsUnexpandedParameterPack()),
      Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
      MemberLoc(NameInfo.getLoc()), IsArrow(isarrow),
      HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
      HadMultipleCandidates(false) {
    assert(memberdecl->getDeclName() == NameInfo.getName());
  }

  // NOTE: this constructor should be used only when it is known that
  // the member name can not provide additional syntactic info
  // (i.e., source locations for C++ operator names or type source info
  // for constructors, destructors and conversion operators).
  MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
             SourceLocation l, QualType ty,
             ExprValueKind VK, ExprObjectKind OK)
    : Expr(MemberExprClass, ty, VK, OK,
           base->isTypeDependent(), base->isValueDependent(),
           base->isInstantiationDependent(),
           base->containsUnexpandedParameterPack()),
      Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
      IsArrow(isarrow),
      HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
      HadMultipleCandidates(false) {}

  static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
                            NestedNameSpecifierLoc QualifierLoc,
                            SourceLocation TemplateKWLoc,
                            ValueDecl *memberdecl, DeclAccessPair founddecl,
                            DeclarationNameInfo MemberNameInfo,
                            const TemplateArgumentListInfo *targs,
                            QualType ty, ExprValueKind VK, ExprObjectKind OK);

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

  /// \brief Retrieve the member declaration to which this expression refers.
  ///
  /// The returned declaration will either be a FieldDecl or (in C++)
  /// a CXXMethodDecl.
  ValueDecl *getMemberDecl() const { return MemberDecl; }
  void setMemberDecl(ValueDecl *D) { MemberDecl = D; }

  /// \brief Retrieves the declaration found by lookup.
  DeclAccessPair getFoundDecl() const {
    if (!HasQualifierOrFoundDecl)
      return DeclAccessPair::make(getMemberDecl(),
                                  getMemberDecl()->getAccess());
    return getMemberQualifier()->FoundDecl;
  }

  /// \brief 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() != 0; }

  /// \brief If the member name was qualified, retrieves the
  /// nested-name-specifier that precedes the member name. Otherwise, returns
  /// NULL.
  NestedNameSpecifier *getQualifier() const {
    if (!HasQualifierOrFoundDecl)
      return 0;

    return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
  }

  /// \brief If the member name was qualified, retrieves the
  /// nested-name-specifier that precedes the member name, with source-location
  /// information.
  NestedNameSpecifierLoc getQualifierLoc() const {
    if (!hasQualifier())
      return NestedNameSpecifierLoc();

    return getMemberQualifier()->QualifierLoc;
  }

  /// \brief Return the optional template keyword and arguments info.
  ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
    if (!HasTemplateKWAndArgsInfo)
      return 0;

    if (!HasQualifierOrFoundDecl)
      return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);

    return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
                                                      getMemberQualifier() + 1);
  }

  /// \brief Return the optional template keyword and arguments info.
  const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
    return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo();
  }

  /// \brief Retrieve the location of the template keyword preceding
  /// the member name, if any.
  SourceLocation getTemplateKeywordLoc() const {
    if (!HasTemplateKWAndArgsInfo) return SourceLocation();
    return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
  }

  /// \brief 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 getTemplateKWAndArgsInfo()->LAngleLoc;
  }

  /// \brief 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 getTemplateKWAndArgsInfo()->RAngleLoc;
  }

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

  /// \brief Determines whether the member name was followed by an
  /// explicit template argument list.
  bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }

  /// \brief Copies the template arguments (if present) into the given
  /// structure.
  void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
    if (hasExplicitTemplateArgs())
      getExplicitTemplateArgs().copyInto(List);
  }

  /// \brief Retrieve the explicit template argument list that
  /// follow the member template name.  This must only be called on an
  /// expression with explicit template arguments.
  ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
    assert(hasExplicitTemplateArgs());
    return *getTemplateKWAndArgsInfo();
  }

  /// \brief Retrieve the explicit template argument list that
  /// followed the member template name.  This must only be called on
  /// an expression with explicit template arguments.
  const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
    return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
  }

  /// \brief Retrieves the optional explicit template arguments.
  /// This points to the same data as getExplicitTemplateArgs(), but
  /// returns null if there are no explicit template arguments.
  const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
    if (!hasExplicitTemplateArgs()) return 0;
    return &getExplicitTemplateArgs();
  }

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

    return getExplicitTemplateArgs().getTemplateArgs();
  }

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

    return getExplicitTemplateArgs().NumTemplateArgs;
  }

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

  bool isArrow() const { return IsArrow; }
  void setArrow(bool A) { 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; }

  SourceRange getSourceRange() const;

  SourceLocation getExprLoc() const { return MemberLoc; }

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

  /// \brief 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 HadMultipleCandidates;
  }
  /// \brief 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) {
    HadMultipleCandidates = V;
  }

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

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

  friend class ASTReader;
  friend class ASTStmtWriter;
};

/// 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,
           tinfo->getType()->isDependentType(),
           init->isValueDependent(),
           (init->isInstantiationDependent() ||
            tinfo->getType()->isInstantiationDependentType()),
           init->containsUnexpandedParameterPack()),
      LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}

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

  SourceRange getSourceRange() const {
    // FIXME: Init should never be null.
    if (!Init)
      return SourceRange();
    if (LParenLoc.isInvalid())
      return Init->getSourceRange();
    return SourceRange(LParenLoc, Init->getLocEnd());
  }

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

  // Iterators
  child_range children() { return 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 {
public:
  typedef clang::CastKind CastKind;

private:
  Stmt *Op;

  void CheckCastConsistency() const;

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

  void setBasePathSize(unsigned basePathSize) {
    CastExprBits.BasePathSize = basePathSize;
    assert(CastExprBits.BasePathSize == basePathSize &&
           "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
  }

protected:
  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
           const CastKind kind, Expr *op, unsigned BasePathSize) :
    Expr(SC, ty, VK, OK_Ordinary,
         // Cast expressions are type-dependent if the type is
         // dependent (C++ [temp.dep.expr]p3).
         ty->isDependentType(),
         // Cast expressions are value-dependent if the type is
         // dependent or if the subexpression is value-dependent.
         ty->isDependentType() || (op && op->isValueDependent()),
         (ty->isInstantiationDependentType() ||
          (op && op->isInstantiationDependent())),
         (ty->containsUnexpandedParameterPack() ||
          op->containsUnexpandedParameterPack())),
    Op(op) {
    assert(kind != CK_Invalid && "creating cast with invalid cast kind");
    CastExprBits.Kind = kind;
    setBasePathSize(BasePathSize);
#ifndef NDEBUG
    CheckCastConsistency();
#endif
  }

  /// \brief Construct an empty cast.
  CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
    : Expr(SC, Empty) {
    setBasePathSize(BasePathSize);
  }

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

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

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

  typedef CXXBaseSpecifier **path_iterator;
  typedef const CXXBaseSpecifier * const *path_const_iterator;
  bool path_empty() const { return CastExprBits.BasePathSize == 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(); }

  void setCastPath(const CXXCastPath &Path);

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

  // Iterators
  child_range children() { return 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 : public CastExpr {
private:
  ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
                   unsigned BasePathLength, ExprValueKind VK)
    : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
  }

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

public:
  enum OnStack_t { OnStack };
  ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
                   ExprValueKind VK)
    : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
  }

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

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

  SourceRange getSourceRange() const {
    return getSubExpr()->getSourceRange();
  }

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

inline Expr *Expr::IgnoreImpCasts() {
  Expr *e = this;
  while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
    e = ice->getSubExpr();
  return e;
}

/// 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,
                   TypeSourceInfo *writtenTy)
    : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}

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

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;
  }
  static bool classof(const ExplicitCastExpr *) { return true; }
};

/// 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 : public ExplicitCastExpr {
  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, TypeSourceInfo *writtenTy,
                 SourceLocation l, SourceLocation r)
    : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
                       writtenTy), LPLoc(l), RPLoc(r) {}

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

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

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

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

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

  SourceRange getSourceRange() const {
    return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == CStyleCastExprClass;
  }
  static bool classof(const CStyleCastExpr *) { return true; }
};

/// \brief 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 {
public:
  typedef BinaryOperatorKind Opcode;

private:
  unsigned Opc : 6;
  SourceLocation OpLoc;

  enum { LHS, RHS, END_EXPR };
  Stmt* SubExprs[END_EXPR];
public:

  BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
                 ExprValueKind VK, ExprObjectKind OK,
                 SourceLocation opLoc)
    : Expr(BinaryOperatorClass, ResTy, VK, OK,
           lhs->isTypeDependent() || rhs->isTypeDependent(),
           lhs->isValueDependent() || rhs->isValueDependent(),
           (lhs->isInstantiationDependent() ||
            rhs->isInstantiationDependent()),
           (lhs->containsUnexpandedParameterPack() ||
            rhs->containsUnexpandedParameterPack())),
      Opc(opc), OpLoc(opLoc) {
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
    assert(!isCompoundAssignmentOp() &&
           "Use ArithAssignBinaryOperator for compound assignments");
  }

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

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

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

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

  SourceRange getSourceRange() const {
    return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
  }

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

  const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); }

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

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

  /// predicates to categorize the respective opcodes.
  bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
  bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
  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_LT && Opc<=BO_NE; }
  bool isComparisonOp() const { return isComparisonOp(getOpcode()); }

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

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

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

protected:
  BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
                 ExprValueKind VK, ExprObjectKind OK,
                 SourceLocation opLoc, bool dead)
    : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
           lhs->isTypeDependent() || rhs->isTypeDependent(),
           lhs->isValueDependent() || rhs->isValueDependent(),
           (lhs->isInstantiationDependent() ||
            rhs->isInstantiationDependent()),
           (lhs->containsUnexpandedParameterPack() ||
            rhs->containsUnexpandedParameterPack())),
      Opc(opc), OpLoc(opLoc) {
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
  }

  BinaryOperator(StmtClass SC, EmptyShell Empty)
    : Expr(SC, Empty), Opc(BO_MulAssign) { }
};

/// 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;
public:
  CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
                         ExprValueKind VK, ExprObjectKind OK,
                         QualType CompLHSType, QualType CompResultType,
                         SourceLocation OpLoc)
    : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),
      ComputationLHSType(CompLHSType),
      ComputationResultType(CompResultType) {
    assert(isCompoundAssignmentOp() &&
           "Only should be used for compound assignments");
  }

  /// \brief Build an empty compound assignment operator expression.
  explicit CompoundAssignOperator(EmptyShell Empty)
    : BinaryOperator(CompoundAssignOperatorClass, Empty) { }

  // 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 CompoundAssignOperator *) { return true; }
  static bool classof(const Stmt *S) {
    return S->getStmtClass() == CompoundAssignOperatorClass;
  }
};

/// 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,
                              bool TD, bool VD, bool ID,
                              bool ContainsUnexpandedParameterPack,
                              SourceLocation qloc,
                              SourceLocation cloc)
    : Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack),
      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;
  }
  static bool classof(const AbstractConditionalOperator *) { return true; }
};

/// 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,
           // FIXME: the type of the conditional operator doesn't
           // depend on the type of the conditional, but the standard
           // seems to imply that it could. File a bug!
           (lhs->isTypeDependent() || rhs->isTypeDependent()),
           (cond->isValueDependent() || lhs->isValueDependent() ||
            rhs->isValueDependent()),
           (cond->isInstantiationDependent() ||
            lhs->isInstantiationDependent() ||
            rhs->isInstantiationDependent()),
           (cond->containsUnexpandedParameterPack() ||
            lhs->containsUnexpandedParameterPack() ||
            rhs->containsUnexpandedParameterPack()),
                                  QLoc, CLoc) {
    SubExprs[COND] = cond;
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
  }

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

  SourceRange getSourceRange() const {
    return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ConditionalOperatorClass;
  }
  static bool classof(const ConditionalOperator *) { return true; }

  // Iterators
  child_range children() {
    return 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,
           (common->isTypeDependent() || rhs->isTypeDependent()),
           (common->isValueDependent() || rhs->isValueDependent()),
           (common->isInstantiationDependent() ||
            rhs->isInstantiationDependent()),
           (common->containsUnexpandedParameterPack() ||
            rhs->containsUnexpandedParameterPack()),
                                  qloc, cloc),
      OpaqueValue(opaqueValue) {
    SubExprs[COMMON] = common;
    SubExprs[COND] = cond;
    SubExprs[LHS] = lhs;
    SubExprs[RHS] = rhs;
    assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
  }

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

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

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

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

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

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

  SourceRange getSourceRange() const {
    return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd());
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == BinaryConditionalOperatorClass;
  }
  static bool classof(const BinaryConditionalOperator *) { return true; }

  // Iterators
  child_range children() {
    return 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, false, false, false,
           false),
      AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}

  /// \brief 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; }

  SourceRange getSourceRange() const {
    return SourceRange(AmpAmpLoc, LabelLoc);
  }

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

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

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

/// 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:
  // FIXME: Does type-dependence need to be computed differently?
  // FIXME: Do we need to compute instantiation instantiation-dependence for
  // statements? (ugh!)
  StmtExpr(CompoundStmt *substmt, QualType T,
           SourceLocation lp, SourceLocation rp) :
    Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
         T->isDependentType(), false, false, false),
    SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }

  /// \brief 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; }

  SourceRange getSourceRange() const {
    return SourceRange(LParenLoc, RParenLoc);
  }

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

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

  // Iterators
  child_range children() { return 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(ASTContext &C, Expr **args, unsigned nexpr,
                    QualType Type, SourceLocation BLoc,
                    SourceLocation RP);

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

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

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

  SourceRange getSourceRange() const {
    return SourceRange(BuiltinLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ShuffleVectorExprClass;
  }
  static bool classof(const ShuffleVectorExpr *) { return true; }

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

  /// \brief 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(ASTContext &C, Expr ** Exprs, unsigned NumExprs);

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

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

/// 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;
public:
  ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
             QualType t, ExprValueKind VK, ExprObjectKind OK,
             SourceLocation RP, bool TypeDependent, bool ValueDependent)
    : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
           (cond->isInstantiationDependent() ||
            lhs->isInstantiationDependent() ||
            rhs->isInstantiationDependent()),
           (cond->containsUnexpandedParameterPack() ||
            lhs->containsUnexpandedParameterPack() ||
            rhs->containsUnexpandedParameterPack())),
      BuiltinLoc(BLoc), RParenLoc(RP) {
      SubExprs[COND] = cond;
      SubExprs[LHS] = lhs;
      SubExprs[RHS] = rhs;
    }

  /// \brief 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 ASTContext &C) const;

  /// getChosenSubExpr - Return the subexpression chosen according to the
  /// condition.
  Expr *getChosenSubExpr(const ASTContext &C) const {
    return isConditionTrue(C) ? 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; }

  SourceRange getSourceRange() const {
    return SourceRange(BuiltinLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ChooseExprClass;
  }
  static bool classof(const ChooseExpr *) { return true; }

  // Iterators
  child_range children() {
    return 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, false, false, false,
           false),
      TokenLoc(Loc) { }

  /// \brief 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; }

  SourceRange getSourceRange() const {
    return SourceRange(TokenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == GNUNullExprClass;
  }
  static bool classof(const GNUNullExpr *) { return true; }

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

/// VAArgExpr, used for the builtin function __builtin_va_arg.
class VAArgExpr : public Expr {
  Stmt *Val;
  TypeSourceInfo *TInfo;
  SourceLocation BuiltinLoc, RParenLoc;
public:
  VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
            SourceLocation RPLoc, QualType t)
    : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
           t->isDependentType(), false,
           (TInfo->getType()->isInstantiationDependentType() ||
            e->isInstantiationDependent()),
           (TInfo->getType()->containsUnexpandedParameterPack() ||
            e->containsUnexpandedParameterPack())),
      Val(e), TInfo(TInfo),
      BuiltinLoc(BLoc),
      RParenLoc(RPLoc) { }

  /// \brief Create an empty __builtin_va_arg expression.
  explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }

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

  TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
  void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }

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

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

  SourceRange getSourceRange() const {
    return SourceRange(BuiltinLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == VAArgExprClass;
  }
  static bool classof(const VAArgExpr *) { return true; }

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

/// @brief 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.
///
/// Given the semantic form of the initializer list, one can retrieve
/// the original syntactic form of that initializer list (if it
/// exists) using getSyntacticForm(). Since many initializer lists
/// have the same syntactic and semantic forms, getSyntacticForm() may
/// return NULL, indicating that the current 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;

  /// Contains the initializer list that describes the syntactic form
  /// written in the source code.
  InitListExpr *SyntacticForm;

  /// \brief 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(ASTContext &C, SourceLocation lbraceloc,
               Expr **initexprs, unsigned numinits,
               SourceLocation rbraceloc);

  /// \brief Build an empty initializer list.
  explicit InitListExpr(ASTContext &C, EmptyShell Empty)
    : Expr(InitListExprClass, Empty), InitExprs(C) { }

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

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

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

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

  /// @brief 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(ASTContext &Context, unsigned NumInits);

  /// @brief 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(ASTContext &C, unsigned Init, Expr *expr);

  /// \brief 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);

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

  /// \brief 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) {
    ArrayFillerOrUnionFieldInit = FD;
  }

  // Explicit InitListExpr's originate from source code (and have valid source
  // locations). Implicit InitListExpr's are created by the semantic analyzer.
  bool isExplicit() {
    return LBraceLoc.isValid() && RBraceLoc.isValid();
  }

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

  /// @brief Retrieve the initializer list that describes the
  /// syntactic form of the initializer.
  ///
  ///
  InitListExpr *getSyntacticForm() const { return SyntacticForm; }
  void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; }

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

  bool initializesStdInitializerList() const {
    return InitListExprBits.InitializesStdInitializerList != 0;
  }
  void setInitializesStdInitializerList(bool ISIL = true) {
    InitListExprBits.InitializesStdInitializerList = ISIL;
  }

  SourceRange getSourceRange() const;

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

  // Iterators
  child_range children() {
    if (InitExprs.empty()) return child_range();
    return 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;
};

/// @brief 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 initalization expression will be 1.0.
class DesignatedInitExpr : public Expr {
public:
  /// \brief 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.
  bool 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;

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


  DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators,
                     const Designator *Designators,
                     SourceLocation EqualOrColonLoc, bool GNUSyntax,
                     Expr **IndexExprs, unsigned NumIndexExprs,
                     Expr *Init);

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

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.
    unsigned DotLoc;

    /// The location of the field name in the designated initializer.
    unsigned 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.
    unsigned LBracketLoc;
    /// The location of the ellipsis separating the start and end
    /// indices. Only valid for GNU array-range designators.
    unsigned EllipsisLoc;
    /// The location of the ']' terminating the array range designator.
    unsigned RBracketLoc;
  };

  /// @brief 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 {
    /// @brief 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() {}

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

    /// @brief Initializes an array designator.
    Designator(unsigned Index, SourceLocation LBracketLoc,
               SourceLocation RBracketLoc)
      : Kind(ArrayDesignator) {
      ArrayOrRange.Index = Index;
      ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
      ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding();
      ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
    }

    /// @brief Initializes a GNU array-range designator.
    Designator(unsigned Index, SourceLocation LBracketLoc,
               SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
      : Kind(ArrayRangeDesignator) {
      ArrayOrRange.Index = Index;
      ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
      ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding();
      ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
    }

    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 0;
      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 SourceLocation::getFromRawEncoding(Field.DotLoc);
    }

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

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

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

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

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

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

  static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
                                    unsigned NumDesignators,
                                    Expr **IndexExprs, unsigned NumIndexExprs,
                                    SourceLocation EqualOrColonLoc,
                                    bool GNUSyntax, Expr *Init);

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

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

  // Iterator access to the designators.
  typedef Designator *designators_iterator;
  designators_iterator designators_begin() { return Designators; }
  designators_iterator designators_end() {
    return Designators + NumDesignators;
  }

  typedef const Designator *const_designators_iterator;
  const_designators_iterator designators_begin() const { return Designators; }
  const_designators_iterator designators_end() const {
    return Designators + NumDesignators;
  }

  typedef std::reverse_iterator<designators_iterator>
          reverse_designators_iterator;
  reverse_designators_iterator designators_rbegin() {
    return reverse_designators_iterator(designators_end());
  }
  reverse_designators_iterator designators_rend() {
    return reverse_designators_iterator(designators_begin());
  }

  typedef std::reverse_iterator<const_designators_iterator>
          const_reverse_designators_iterator;
  const_reverse_designators_iterator designators_rbegin() const {
    return const_reverse_designators_iterator(designators_end());
  }
  const_reverse_designators_iterator designators_rend() const {
    return const_reverse_designators_iterator(designators_begin());
  }

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

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

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

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

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

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

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

  /// \brief 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) {
    assert(Idx < NumSubExprs && "Subscript out of range");
    char* Ptr = static_cast<char*>(static_cast<void *>(this));
    Ptr += sizeof(DesignatedInitExpr);
    return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx];
  }

  void setSubExpr(unsigned Idx, Expr *E) {
    assert(Idx < NumSubExprs && "Subscript out of range");
    char* Ptr = static_cast<char*>(static_cast<void *>(this));
    Ptr += sizeof(DesignatedInitExpr);
    reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E;
  }

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

  SourceRange getDesignatorsSourceRange() const;

  SourceRange getSourceRange() const;

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

  // Iterators
  child_range children() {
    Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
    return child_range(begin, begin + NumSubExprs);
  }
};

/// \brief 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,
           false, false, ty->isInstantiationDependentType(), false) { }

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

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

  SourceRange getSourceRange() const {
    return SourceRange();
  }

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


class ParenListExpr : public Expr {
  Stmt **Exprs;
  unsigned NumExprs;
  SourceLocation LParenLoc, RParenLoc;

public:
  ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
                unsigned numexprs, SourceLocation rparenloc);

  /// \brief Build an empty paren list.
  explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }

  unsigned getNumExprs() const { return NumExprs; }

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

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

  Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }

  SourceLocation getLParenLoc() const { return LParenLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }

  SourceRange getSourceRange() const {
    return SourceRange(LParenLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ParenListExprClass;
  }
  static bool classof(const ParenListExpr *) { return true; }

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

  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};


/// \brief 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 : public Expr {
  enum { CONTROLLING, END_EXPR };
  TypeSourceInfo **AssocTypes;
  Stmt **SubExprs;
  unsigned NumAssocs, ResultIndex;
  SourceLocation GenericLoc, DefaultLoc, RParenLoc;

public:
  GenericSelectionExpr(ASTContext &Context,
                       SourceLocation GenericLoc, Expr *ControllingExpr,
                       TypeSourceInfo **AssocTypes, Expr **AssocExprs,
                       unsigned NumAssocs, SourceLocation DefaultLoc,
                       SourceLocation RParenLoc,
                       bool ContainsUnexpandedParameterPack,
                       unsigned ResultIndex);

  /// This constructor is used in the result-dependent case.
  GenericSelectionExpr(ASTContext &Context,
                       SourceLocation GenericLoc, Expr *ControllingExpr,
                       TypeSourceInfo **AssocTypes, Expr **AssocExprs,
                       unsigned NumAssocs, SourceLocation DefaultLoc,
                       SourceLocation RParenLoc,
                       bool ContainsUnexpandedParameterPack);

  explicit GenericSelectionExpr(EmptyShell Empty)
    : Expr(GenericSelectionExprClass, Empty) { }

  unsigned getNumAssocs() const { return NumAssocs; }

  SourceLocation getGenericLoc() const { return GenericLoc; }
  SourceLocation getDefaultLoc() const { return DefaultLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }

  const Expr *getAssocExpr(unsigned i) const {
    return cast<Expr>(SubExprs[END_EXPR+i]);
  }
  Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }

  const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
    return AssocTypes[i];
  }
  TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }

  QualType getAssocType(unsigned i) const {
    if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
      return TS->getType();
    else
      return QualType();
  }

  const Expr *getControllingExpr() const {
    return cast<Expr>(SubExprs[CONTROLLING]);
  }
  Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); }

  /// Whether this generic selection is result-dependent.
  bool isResultDependent() const { return ResultIndex == -1U; }

  /// 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");
    return ResultIndex;
  }

  /// The generic selection's result expression.  Defined only if the
  /// generic selection is not result-dependent.
  const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
  Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }

  SourceRange getSourceRange() const {
    return SourceRange(GenericLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == GenericSelectionExprClass;
  }
  static bool classof(const GenericSelectionExpr *) { return true; }

  child_range children() {
    return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
  }

  friend class ASTStmtReader;
};

//===----------------------------------------------------------------------===//
// 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->isTypeDependent(), base->isValueDependent(),
           base->isInstantiationDependent(),
           base->containsUnexpandedParameterPack()),
      Base(base), Accessor(&accessor), AccessorLoc(loc) {}

  /// \brief 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<unsigned> &Elts) const;

  SourceRange getSourceRange() const {
    return SourceRange(getBase()->getLocStart(), 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;
  }
  static bool classof(const ExtVectorElementExpr *) { return true; }

  // Iterators
  child_range children() { return 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,
           ty->isDependentType(), ty->isDependentType(),
           ty->isInstantiationDependentType() || BD->isDependentContext(),
           false),
      TheBlock(BD) {}

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

  SourceRange getSourceRange() const {
    return SourceRange(getCaretLocation(), getBody()->getLocEnd());
  }

  /// getFunctionType - Return the underlying function type for this block.
  const FunctionProtoType *getFunctionType() const;

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

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

/// BlockDeclRefExpr - A reference to a local variable declared in an
/// enclosing scope.
class BlockDeclRefExpr : public Expr {
  VarDecl *D;
  SourceLocation Loc;
  bool IsByRef : 1;
  bool ConstQualAdded : 1;
public:
  BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
                   SourceLocation l, bool ByRef, bool constAdded = false);

  // \brief Build an empty reference to a declared variable in a
  // block.
  explicit BlockDeclRefExpr(EmptyShell Empty)
    : Expr(BlockDeclRefExprClass, Empty) { }

  VarDecl *getDecl() { return D; }
  const VarDecl *getDecl() const { return D; }
  void setDecl(VarDecl *VD) { D = VD; }

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

  SourceRange getSourceRange() const { return SourceRange(Loc); }

  bool isByRef() const { return IsByRef; }
  void setByRef(bool BR) { IsByRef = BR; }

  bool isConstQualAdded() const { return ConstQualAdded; }
  void setConstQualAdded(bool C) { ConstQualAdded = C; }

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

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

/// 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 { // Should this be an ExplicitCastExpr?
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,
           DstType->isDependentType(),
           DstType->isDependentType() || SrcExpr->isValueDependent(),
           (DstType->isInstantiationDependentType() ||
            SrcExpr->isInstantiationDependent()),
           (DstType->containsUnexpandedParameterPack() ||
            SrcExpr->containsUnexpandedParameterPack())),
  SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}

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

  SourceRange getSourceRange() const {
    return SourceRange(BuiltinLoc, RParenLoc);
  }

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

  // Iterators
  child_range children() { return 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 : public 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 reinterpret_cast<Expr**>(this + 1); }
  const Expr * const *getSubExprsBuffer() const {
    return reinterpret_cast<const Expr * const *>(this + 1);
  }

  friend class ASTStmtReader;

  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 { NoResult = ~0U };

  static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic,
                                  ArrayRef<Expr*> semantic,
                                  unsigned resultIndex);

  static PseudoObjectExpr *Create(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 0;
    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();
  }
  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 {
    return getSyntacticForm()->getExprLoc();
  }
  SourceRange getSourceRange() const {
    return getSyntacticForm()->getSourceRange();
  }

  child_range children() {
    Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());
    return child_range(cs, cs + getNumSubExprs());
  }

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

/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
/// similarly-named C++0x instructions.  All of these instructions take one
/// primary pointer and at least one memory order.
class AtomicExpr : public Expr {
public:
  enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg,
                  Add, Sub, And, Or, Xor, Init };
private:
  enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR };
  Stmt* SubExprs[END_EXPR];
  unsigned NumSubExprs;
  SourceLocation BuiltinLoc, RParenLoc;
  AtomicOp Op;

public:
  AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t,
             AtomicOp op, SourceLocation RP);

  /// \brief Build an empty AtomicExpr.
  explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }

  Expr *getPtr() const {
    return cast<Expr>(SubExprs[PTR]);
  }
  void setPtr(Expr *E) {
    SubExprs[PTR] = E;
  }
  Expr *getOrder() const {
    return cast<Expr>(SubExprs[ORDER]);
  }
  void setOrder(Expr *E) {
    SubExprs[ORDER] = E;
  }
  Expr *getVal1() const {
    if (Op == Init)
      return cast<Expr>(SubExprs[ORDER]);
    assert(NumSubExprs >= 3);
    return cast<Expr>(SubExprs[VAL1]);
  }
  void setVal1(Expr *E) {
    if (Op == Init) {
      SubExprs[ORDER] = E;
      return;
    }
    assert(NumSubExprs >= 3);
    SubExprs[VAL1] = E;
  }
  Expr *getOrderFail() const {
    assert(NumSubExprs == 5);
    return cast<Expr>(SubExprs[ORDER_FAIL]);
  }
  void setOrderFail(Expr *E) {
    assert(NumSubExprs == 5);
    SubExprs[ORDER_FAIL] = E;
  }
  Expr *getVal2() const {
    assert(NumSubExprs == 5);
    return cast<Expr>(SubExprs[VAL2]);
  }
  void setVal2(Expr *E) {
    assert(NumSubExprs == 5);
    SubExprs[VAL2] = E;
  }

  AtomicOp getOp() const { return Op; }
  void setOp(AtomicOp op) { Op = op; }
  unsigned getNumSubExprs() { return NumSubExprs; }
  void setNumSubExprs(unsigned num) { NumSubExprs = num; }

  Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }

  bool isVolatile() const {
    return getPtr()->getType()->getPointeeType().isVolatileQualified();
  }

  bool isCmpXChg() const {
    return getOp() == AtomicExpr::CmpXchgStrong ||
           getOp() == AtomicExpr::CmpXchgWeak;
  }

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

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

  SourceRange getSourceRange() const {
    return SourceRange(BuiltinLoc, RParenLoc);
  }
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == AtomicExprClass;
  }
  static bool classof(const AtomicExpr *) { return true; }

  // Iterators
  child_range children() {
    return child_range(SubExprs, SubExprs+NumSubExprs);
  }
};
}  // end namespace clang

#endif
