//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for C++ expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "TypeLocBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
using namespace sema;

ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
                                   IdentifierInfo &II,
                                   SourceLocation NameLoc,
                                   Scope *S, CXXScopeSpec &SS,
                                   ParsedType ObjectTypePtr,
                                   bool EnteringContext) {
  // Determine where to perform name lookup.

  // FIXME: This area of the standard is very messy, and the current
  // wording is rather unclear about which scopes we search for the
  // destructor name; see core issues 399 and 555. Issue 399 in
  // particular shows where the current description of destructor name
  // lookup is completely out of line with existing practice, e.g.,
  // this appears to be ill-formed:
  //
  //   namespace N {
  //     template <typename T> struct S {
  //       ~S();
  //     };
  //   }
  //
  //   void f(N::S<int>* s) {
  //     s->N::S<int>::~S();
  //   }
  //
  // See also PR6358 and PR6359.
  // For this reason, we're currently only doing the C++03 version of this
  // code; the C++0x version has to wait until we get a proper spec.
  QualType SearchType;
  DeclContext *LookupCtx = 0;
  bool isDependent = false;
  bool LookInScope = false;

  // If we have an object type, it's because we are in a
  // pseudo-destructor-expression or a member access expression, and
  // we know what type we're looking for.
  if (ObjectTypePtr)
    SearchType = GetTypeFromParser(ObjectTypePtr);

  if (SS.isSet()) {
    NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();

    bool AlreadySearched = false;
    bool LookAtPrefix = true;
    // C++ [basic.lookup.qual]p6:
    //   If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
    //   the type-names are looked up as types in the scope designated by the
    //   nested-name-specifier. In a qualified-id of the form:
    //
    //     ::[opt] nested-name-specifier  ~ class-name
    //
    //   where the nested-name-specifier designates a namespace scope, and in
    //   a qualified-id of the form:
    //
    //     ::opt nested-name-specifier class-name ::  ~ class-name
    //
    //   the class-names are looked up as types in the scope designated by
    //   the nested-name-specifier.
    //
    // Here, we check the first case (completely) and determine whether the
    // code below is permitted to look at the prefix of the
    // nested-name-specifier.
    DeclContext *DC = computeDeclContext(SS, EnteringContext);
    if (DC && DC->isFileContext()) {
      AlreadySearched = true;
      LookupCtx = DC;
      isDependent = false;
    } else if (DC && isa<CXXRecordDecl>(DC))
      LookAtPrefix = false;

    // The second case from the C++03 rules quoted further above.
    NestedNameSpecifier *Prefix = 0;
    if (AlreadySearched) {
      // Nothing left to do.
    } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
      CXXScopeSpec PrefixSS;
      PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
      LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
      isDependent = isDependentScopeSpecifier(PrefixSS);
    } else if (ObjectTypePtr) {
      LookupCtx = computeDeclContext(SearchType);
      isDependent = SearchType->isDependentType();
    } else {
      LookupCtx = computeDeclContext(SS, EnteringContext);
      isDependent = LookupCtx && LookupCtx->isDependentContext();
    }

    LookInScope = false;
  } else if (ObjectTypePtr) {
    // C++ [basic.lookup.classref]p3:
    //   If the unqualified-id is ~type-name, the type-name is looked up
    //   in the context of the entire postfix-expression. If the type T
    //   of the object expression is of a class type C, the type-name is
    //   also looked up in the scope of class C. At least one of the
    //   lookups shall find a name that refers to (possibly
    //   cv-qualified) T.
    LookupCtx = computeDeclContext(SearchType);
    isDependent = SearchType->isDependentType();
    assert((isDependent || !SearchType->isIncompleteType()) &&
           "Caller should have completed object type");

    LookInScope = true;
  } else {
    // Perform lookup into the current scope (only).
    LookInScope = true;
  }

  TypeDecl *NonMatchingTypeDecl = 0;
  LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
  for (unsigned Step = 0; Step != 2; ++Step) {
    // Look for the name first in the computed lookup context (if we
    // have one) and, if that fails to find a match, in the scope (if
    // we're allowed to look there).
    Found.clear();
    if (Step == 0 && LookupCtx)
      LookupQualifiedName(Found, LookupCtx);
    else if (Step == 1 && LookInScope && S)
      LookupName(Found, S);
    else
      continue;

    // FIXME: Should we be suppressing ambiguities here?
    if (Found.isAmbiguous())
      return ParsedType();

    if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
      QualType T = Context.getTypeDeclType(Type);

      if (SearchType.isNull() || SearchType->isDependentType() ||
          Context.hasSameUnqualifiedType(T, SearchType)) {
        // We found our type!

        return ParsedType::make(T);
      }

      if (!SearchType.isNull())
        NonMatchingTypeDecl = Type;
    }

    // If the name that we found is a class template name, and it is
    // the same name as the template name in the last part of the
    // nested-name-specifier (if present) or the object type, then
    // this is the destructor for that class.
    // FIXME: This is a workaround until we get real drafting for core
    // issue 399, for which there isn't even an obvious direction.
    if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) {
      QualType MemberOfType;
      if (SS.isSet()) {
        if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
          // Figure out the type of the context, if it has one.
          if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx))
            MemberOfType = Context.getTypeDeclType(Record);
        }
      }
      if (MemberOfType.isNull())
        MemberOfType = SearchType;

      if (MemberOfType.isNull())
        continue;

      // We're referring into a class template specialization. If the
      // class template we found is the same as the template being
      // specialized, we found what we are looking for.
      if (const RecordType *Record = MemberOfType->getAs<RecordType>()) {
        if (ClassTemplateSpecializationDecl *Spec
              = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
          if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
                Template->getCanonicalDecl())
            return ParsedType::make(MemberOfType);
        }

        continue;
      }

      // We're referring to an unresolved class template
      // specialization. Determine whether we class template we found
      // is the same as the template being specialized or, if we don't
      // know which template is being specialized, that it at least
      // has the same name.
      if (const TemplateSpecializationType *SpecType
            = MemberOfType->getAs<TemplateSpecializationType>()) {
        TemplateName SpecName = SpecType->getTemplateName();

        // The class template we found is the same template being
        // specialized.
        if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
          if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
            return ParsedType::make(MemberOfType);

          continue;
        }

        // The class template we found has the same name as the
        // (dependent) template name being specialized.
        if (DependentTemplateName *DepTemplate
                                    = SpecName.getAsDependentTemplateName()) {
          if (DepTemplate->isIdentifier() &&
              DepTemplate->getIdentifier() == Template->getIdentifier())
            return ParsedType::make(MemberOfType);

          continue;
        }
      }
    }
  }

  if (isDependent) {
    // We didn't find our type, but that's okay: it's dependent
    // anyway.
    
    // FIXME: What if we have no nested-name-specifier?
    QualType T = CheckTypenameType(ETK_None, SourceLocation(),
                                   SS.getWithLocInContext(Context),
                                   II, NameLoc);
    return ParsedType::make(T);
  }

  if (NonMatchingTypeDecl) {
    QualType T = Context.getTypeDeclType(NonMatchingTypeDecl);
    Diag(NameLoc, diag::err_destructor_expr_type_mismatch)
      << T << SearchType;
    Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here)
      << T;
  } else if (ObjectTypePtr)
    Diag(NameLoc, diag::err_ident_in_dtor_not_a_type)
      << &II;
  else
    Diag(NameLoc, diag::err_destructor_class_name);

  return ParsedType();
}

ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
    if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
      return ParsedType();
    assert(DS.getTypeSpecType() == DeclSpec::TST_decltype 
           && "only get destructor types from declspecs");
    QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
    QualType SearchType = GetTypeFromParser(ObjectType);
    if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) {
      return ParsedType::make(T);
    }
      
    Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch)
      << T << SearchType;
    return ParsedType();
}

/// \brief Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
                                SourceLocation TypeidLoc,
                                TypeSourceInfo *Operand,
                                SourceLocation RParenLoc) {
  // C++ [expr.typeid]p4:
  //   The top-level cv-qualifiers of the lvalue expression or the type-id
  //   that is the operand of typeid are always ignored.
  //   If the type of the type-id is a class type or a reference to a class
  //   type, the class shall be completely-defined.
  Qualifiers Quals;
  QualType T
    = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(),
                                      Quals);
  if (T->getAs<RecordType>() &&
      RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
    return ExprError();

  return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
                                           Operand,
                                           SourceRange(TypeidLoc, RParenLoc)));
}

/// \brief Build a C++ typeid expression with an expression operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
                                SourceLocation TypeidLoc,
                                Expr *E,
                                SourceLocation RParenLoc) {
  bool isUnevaluatedOperand = true;
  if (E && !E->isTypeDependent()) {
    if (E->getType()->isPlaceholderType()) {
      ExprResult result = CheckPlaceholderExpr(E);
      if (result.isInvalid()) return ExprError();
      E = result.take();
    }

    QualType T = E->getType();
    if (const RecordType *RecordT = T->getAs<RecordType>()) {
      CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
      // C++ [expr.typeid]p3:
      //   [...] If the type of the expression is a class type, the class
      //   shall be completely-defined.
      if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
        return ExprError();

      // C++ [expr.typeid]p3:
      //   When typeid is applied to an expression other than an glvalue of a
      //   polymorphic class type [...] [the] expression is an unevaluated
      //   operand. [...]
      if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
        isUnevaluatedOperand = false;

        // We require a vtable to query the type at run time.
        MarkVTableUsed(TypeidLoc, RecordD);
      }
    }

    // C++ [expr.typeid]p4:
    //   [...] If the type of the type-id is a reference to a possibly
    //   cv-qualified type, the result of the typeid expression refers to a
    //   std::type_info object representing the cv-unqualified referenced
    //   type.
    Qualifiers Quals;
    QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
    if (!Context.hasSameType(T, UnqualT)) {
      T = UnqualT;
      E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).take();
    }
  }

  // If this is an unevaluated operand, clear out the set of
  // declaration references we have been computing and eliminate any
  // temporaries introduced in its computation.
  if (isUnevaluatedOperand)
    ExprEvalContexts.back().Context = Unevaluated;

  return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
                                           E,
                                           SourceRange(TypeidLoc, RParenLoc)));
}

/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression);
ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
  // Find the std::type_info type.
  if (!getStdNamespace())
    return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));

  if (!CXXTypeInfoDecl) {
    IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
    LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
    LookupQualifiedName(R, getStdNamespace());
    CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
    if (!CXXTypeInfoDecl)
      return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
  }

  QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl);

  if (isType) {
    // The operand is a type; handle it as such.
    TypeSourceInfo *TInfo = 0;
    QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
                                   &TInfo);
    if (T.isNull())
      return ExprError();

    if (!TInfo)
      TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);

    return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc);
  }

  // The operand is an expression.
  return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
}

/// Retrieve the UuidAttr associated with QT.
static UuidAttr *GetUuidAttrOfType(QualType QT) {
  // Optionally remove one level of pointer, reference or array indirection.
  const Type *Ty = QT.getTypePtr();;
  if (QT->isPointerType() || QT->isReferenceType())
    Ty = QT->getPointeeType().getTypePtr();
  else if (QT->isArrayType())
    Ty = cast<ArrayType>(QT)->getElementType().getTypePtr();

  // Loop all record redeclaration looking for an uuid attribute.
  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
  for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
       E = RD->redecls_end(); I != E; ++I) {
    if (UuidAttr *Uuid = I->getAttr<UuidAttr>())
      return Uuid;
  }

  return 0;
}

/// \brief Build a Microsoft __uuidof expression with a type operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
                                SourceLocation TypeidLoc,
                                TypeSourceInfo *Operand,
                                SourceLocation RParenLoc) {
  if (!Operand->getType()->isDependentType()) {
    if (!GetUuidAttrOfType(Operand->getType()))
      return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
  }

  // FIXME: add __uuidof semantic analysis for type operand.
  return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
                                           Operand,
                                           SourceRange(TypeidLoc, RParenLoc)));
}

/// \brief Build a Microsoft __uuidof expression with an expression operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
                                SourceLocation TypeidLoc,
                                Expr *E,
                                SourceLocation RParenLoc) {
  if (!E->getType()->isDependentType()) {
    if (!GetUuidAttrOfType(E->getType()) &&
        !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
      return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
  }
  // FIXME: add __uuidof semantic analysis for type operand.
  return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
                                           E,
                                           SourceRange(TypeidLoc, RParenLoc)));
}

/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression);
ExprResult
Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
  // If MSVCGuidDecl has not been cached, do the lookup.
  if (!MSVCGuidDecl) {
    IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID");
    LookupResult R(*this, GuidII, SourceLocation(), LookupTagName);
    LookupQualifiedName(R, Context.getTranslationUnitDecl());
    MSVCGuidDecl = R.getAsSingle<RecordDecl>();
    if (!MSVCGuidDecl)
      return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof));
  }

  QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl);

  if (isType) {
    // The operand is a type; handle it as such.
    TypeSourceInfo *TInfo = 0;
    QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
                                   &TInfo);
    if (T.isNull())
      return ExprError();

    if (!TInfo)
      TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);

    return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc);
  }

  // The operand is an expression.
  return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
}

/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult
Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
  assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
         "Unknown C++ Boolean value!");
  return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true,
                                                Context.BoolTy, OpLoc));
}

/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
ExprResult
Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
  return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
}

/// ActOnCXXThrow - Parse throw expressions.
ExprResult
Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) {
  bool IsThrownVarInScope = false;
  if (Ex) {
    // C++0x [class.copymove]p31:
    //   When certain criteria are met, an implementation is allowed to omit the 
    //   copy/move construction of a class object [...]
    //
    //     - in a throw-expression, when the operand is the name of a 
    //       non-volatile automatic object (other than a function or catch-
    //       clause parameter) whose scope does not extend beyond the end of the 
    //       innermost enclosing try-block (if there is one), the copy/move 
    //       operation from the operand to the exception object (15.1) can be 
    //       omitted by constructing the automatic object directly into the 
    //       exception object
    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens()))
      if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
        if (Var->hasLocalStorage() && !Var->getType().isVolatileQualified()) {
          for( ; S; S = S->getParent()) {
            if (S->isDeclScope(Var)) {
              IsThrownVarInScope = true;
              break;
            }
            
            if (S->getFlags() &
                (Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
                 Scope::FunctionPrototypeScope | Scope::ObjCMethodScope |
                 Scope::TryScope))
              break;
          }
        }
      }
  }
  
  return BuildCXXThrow(OpLoc, Ex, IsThrownVarInScope);
}

ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, 
                               bool IsThrownVarInScope) {
  // Don't report an error if 'throw' is used in system headers.
  if (!getLangOptions().CXXExceptions &&
      !getSourceManager().isInSystemHeader(OpLoc))
    Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
  
  if (Ex && !Ex->isTypeDependent()) {
    ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope);
    if (ExRes.isInvalid())
      return ExprError();
    Ex = ExRes.take();
  }
  
  return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc,
                                          IsThrownVarInScope));
}

/// CheckCXXThrowOperand - Validate the operand of a throw.
ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
                                      bool IsThrownVarInScope) {
  // C++ [except.throw]p3:
  //   A throw-expression initializes a temporary object, called the exception
  //   object, the type of which is determined by removing any top-level
  //   cv-qualifiers from the static type of the operand of throw and adjusting
  //   the type from "array of T" or "function returning T" to "pointer to T"
  //   or "pointer to function returning T", [...]
  if (E->getType().hasQualifiers())
    E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
                          E->getValueKind()).take();

  ExprResult Res = DefaultFunctionArrayConversion(E);
  if (Res.isInvalid())
    return ExprError();
  E = Res.take();

  //   If the type of the exception would be an incomplete type or a pointer
  //   to an incomplete type other than (cv) void the program is ill-formed.
  QualType Ty = E->getType();
  bool isPointer = false;
  if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
    Ty = Ptr->getPointeeType();
    isPointer = true;
  }
  if (!isPointer || !Ty->isVoidType()) {
    if (RequireCompleteType(ThrowLoc, Ty,
                            PDiag(isPointer ? diag::err_throw_incomplete_ptr
                                            : diag::err_throw_incomplete)
                              << E->getSourceRange()))
      return ExprError();

    if (RequireNonAbstractType(ThrowLoc, E->getType(),
                               PDiag(diag::err_throw_abstract_type)
                                 << E->getSourceRange()))
      return ExprError();
  }

  // Initialize the exception result.  This implicitly weeds out
  // abstract types or types with inaccessible copy constructors.
  
  // C++0x [class.copymove]p31:
  //   When certain criteria are met, an implementation is allowed to omit the 
  //   copy/move construction of a class object [...]
  //
  //     - in a throw-expression, when the operand is the name of a 
  //       non-volatile automatic object (other than a function or catch-clause 
  //       parameter) whose scope does not extend beyond the end of the 
  //       innermost enclosing try-block (if there is one), the copy/move 
  //       operation from the operand to the exception object (15.1) can be 
  //       omitted by constructing the automatic object directly into the 
  //       exception object
  const VarDecl *NRVOVariable = 0;
  if (IsThrownVarInScope)
    NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
  
  InitializedEntity Entity =
      InitializedEntity::InitializeException(ThrowLoc, E->getType(),
                                             /*NRVO=*/NRVOVariable != 0);
  Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
                                        QualType(), E,
                                        IsThrownVarInScope);
  if (Res.isInvalid())
    return ExprError();
  E = Res.take();

  // If the exception has class type, we need additional handling.
  const RecordType *RecordTy = Ty->getAs<RecordType>();
  if (!RecordTy)
    return Owned(E);
  CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());

  // If we are throwing a polymorphic class type or pointer thereof,
  // exception handling will make use of the vtable.
  MarkVTableUsed(ThrowLoc, RD);

  // If a pointer is thrown, the referenced object will not be destroyed.
  if (isPointer)
    return Owned(E);

  // If the class has a non-trivial destructor, we must be able to call it.
  if (RD->hasTrivialDestructor())
    return Owned(E);

  CXXDestructorDecl *Destructor
    = const_cast<CXXDestructorDecl*>(LookupDestructor(RD));
  if (!Destructor)
    return Owned(E);

  MarkDeclarationReferenced(E->getExprLoc(), Destructor);
  CheckDestructorAccess(E->getExprLoc(), Destructor,
                        PDiag(diag::err_access_dtor_exception) << Ty);
  return Owned(E);
}

QualType Sema::getCurrentThisType() {
  DeclContext *DC = getFunctionLevelDeclContext();
  QualType ThisTy;
  if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
    if (method && method->isInstance())
      ThisTy = method->getThisType(Context);
  } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
    // C++0x [expr.prim]p4:
    //   Otherwise, if a member-declarator declares a non-static data member
    // of a class X, the expression this is a prvalue of type "pointer to X"
    // within the optional brace-or-equal-initializer.
    Scope *S = getScopeForContext(DC);
    if (!S || S->getFlags() & Scope::ThisScope)
      ThisTy = Context.getPointerType(Context.getRecordType(RD));
  }

  return ThisTy;
}

void Sema::CheckCXXThisCapture(SourceLocation Loc) {
  // We don't need to capture this in an unevaluated context.
  if (ExprEvalContexts.back().Context == Unevaluated)
    return;

  // Otherwise, check that we can capture 'this'.
  unsigned NumClosures = 0;
  for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) {
    if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[idx])) {
      if (LSI->CapturesCXXThis) {
        // This lambda already captures 'this'; there isn't anything more to do.
        break;
      }
      if (LSI->Default == LCD_ByRef) {
        // This lambda can implicitly capture 'this'; continue looking upwards.
        // FIXME: Is this check correct?  The rules in the standard are a bit
        // unclear.
        NumClosures++;
        continue;
      }
      // This lambda can't implicitly capture 'this'; fail out.
      // (We need to delay the diagnostic in the
      // PotentiallyPotentiallyEvaluated case because it doesn't apply to
      // unevaluated contexts.)
      if (ExprEvalContexts.back().Context == PotentiallyPotentiallyEvaluated)
        ExprEvalContexts.back()
            .addDiagnostic(Loc, PDiag(diag::err_implicit_this_capture));
      else
        Diag(Loc, diag::err_implicit_this_capture);
      return;
    }
    if (isa<BlockScopeInfo>(FunctionScopes[idx])) {
      NumClosures++;
      continue;
    }
    break;
  }

  // Mark that we're implicitly capturing 'this' in all the scopes we skipped.
  // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
  // contexts.
  for (unsigned idx = FunctionScopes.size() - 1;
       NumClosures; --idx, --NumClosures) {
    if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(FunctionScopes[idx])) {
      BSI->CapturesCXXThis = true;
    } else {
      LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[idx]);
      assert(LSI && "Unexpected closure");
      LSI->CapturesCXXThis = true;
      LSI->Captures.push_back(LambdaScopeInfo::Capture::ThisCapture);
    }
  }
}

ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
  /// C++ 9.3.2: In the body of a non-static member function, the keyword this
  /// is a non-lvalue expression whose value is the address of the object for
  /// which the function is called.

  QualType ThisTy = getCurrentThisType();
  if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);

  CheckCXXThisCapture(Loc);
  return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
}

ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
                                SourceLocation LParenLoc,
                                MultiExprArg exprs,
                                SourceLocation RParenLoc) {
  if (!TypeRep)
    return ExprError();

  TypeSourceInfo *TInfo;
  QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
  if (!TInfo)
    TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());

  return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
}

/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
/// Can be interpreted either as function-style casting ("int(x)")
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
ExprResult
Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
                                SourceLocation LParenLoc,
                                MultiExprArg exprs,
                                SourceLocation RParenLoc) {
  QualType Ty = TInfo->getType();
  unsigned NumExprs = exprs.size();
  Expr **Exprs = (Expr**)exprs.get();
  SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
  SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);

  if (Ty->isDependentType() ||
      CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
    exprs.release();

    return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo,
                                                    LParenLoc,
                                                    Exprs, NumExprs,
                                                    RParenLoc));
  }

  if (Ty->isArrayType())
    return ExprError(Diag(TyBeginLoc,
                          diag::err_value_init_for_array_type) << FullRange);
  if (!Ty->isVoidType() &&
      RequireCompleteType(TyBeginLoc, Ty,
                          PDiag(diag::err_invalid_incomplete_type_use)
                            << FullRange))
    return ExprError();

  if (RequireNonAbstractType(TyBeginLoc, Ty,
                             diag::err_allocation_of_abstract_type))
    return ExprError();


  // C++ [expr.type.conv]p1:
  // If the expression list is a single expression, the type conversion
  // expression is equivalent (in definedness, and if defined in meaning) to the
  // corresponding cast expression.
  if (NumExprs == 1) {
    Expr *Arg = Exprs[0];
    exprs.release();
    return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
  }

  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
  InitializationKind Kind
    = NumExprs ? InitializationKind::CreateDirect(TyBeginLoc,
                                                  LParenLoc, RParenLoc)
               : InitializationKind::CreateValue(TyBeginLoc,
                                                 LParenLoc, RParenLoc);
  InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));

  // FIXME: Improve AST representation?
  return move(Result);
}

/// doesUsualArrayDeleteWantSize - Answers whether the usual
/// operator delete[] for the given type has a size_t parameter.
static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
                                         QualType allocType) {
  const RecordType *record =
    allocType->getBaseElementTypeUnsafe()->getAs<RecordType>();
  if (!record) return false;

  // Try to find an operator delete[] in class scope.

  DeclarationName deleteName =
    S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
  LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName);
  S.LookupQualifiedName(ops, record->getDecl());

  // We're just doing this for information.
  ops.suppressDiagnostics();

  // Very likely: there's no operator delete[].
  if (ops.empty()) return false;

  // If it's ambiguous, it should be illegal to call operator delete[]
  // on this thing, so it doesn't matter if we allocate extra space or not.
  if (ops.isAmbiguous()) return false;

  LookupResult::Filter filter = ops.makeFilter();
  while (filter.hasNext()) {
    NamedDecl *del = filter.next()->getUnderlyingDecl();

    // C++0x [basic.stc.dynamic.deallocation]p2:
    //   A template instance is never a usual deallocation function,
    //   regardless of its signature.
    if (isa<FunctionTemplateDecl>(del)) {
      filter.erase();
      continue;
    }

    // C++0x [basic.stc.dynamic.deallocation]p2:
    //   If class T does not declare [an operator delete[] with one
    //   parameter] but does declare a member deallocation function
    //   named operator delete[] with exactly two parameters, the
    //   second of which has type std::size_t, then this function
    //   is a usual deallocation function.
    if (!cast<CXXMethodDecl>(del)->isUsualDeallocationFunction()) {
      filter.erase();
      continue;
    }
  }
  filter.done();

  if (!ops.isSingleResult()) return false;

  const FunctionDecl *del = cast<FunctionDecl>(ops.getFoundDecl());
  return (del->getNumParams() == 2);
}

/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
/// @code new (memory) int[size][4] @endcode
/// or
/// @code ::new Foo(23, "hello") @endcode
/// For the interpretation of this heap of arguments, consult the base version.
ExprResult
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
                  SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
                  SourceLocation PlacementRParen, SourceRange TypeIdParens,
                  Declarator &D, SourceLocation ConstructorLParen,
                  MultiExprArg ConstructorArgs,
                  SourceLocation ConstructorRParen) {
  bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;

  Expr *ArraySize = 0;
  // If the specified type is an array, unwrap it and save the expression.
  if (D.getNumTypeObjects() > 0 &&
      D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
    DeclaratorChunk &Chunk = D.getTypeObject(0);
    if (TypeContainsAuto)
      return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto)
        << D.getSourceRange());
    if (Chunk.Arr.hasStatic)
      return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
        << D.getSourceRange());
    if (!Chunk.Arr.NumElts)
      return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
        << D.getSourceRange());

    ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
    D.DropFirstTypeObject();
  }

  // Every dimension shall be of constant size.
  if (ArraySize) {
    for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
      if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
        break;

      DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
      if (Expr *NumElts = (Expr *)Array.NumElts) {
        if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
            !NumElts->isIntegerConstantExpr(Context)) {
          Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst)
            << NumElts->getSourceRange();
          return ExprError();
        }
      }
    }
  }

  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
  QualType AllocType = TInfo->getType();
  if (D.isInvalidType())
    return ExprError();

  return BuildCXXNew(StartLoc, UseGlobal,
                     PlacementLParen,
                     move(PlacementArgs),
                     PlacementRParen,
                     TypeIdParens,
                     AllocType,
                     TInfo,
                     ArraySize,
                     ConstructorLParen,
                     move(ConstructorArgs),
                     ConstructorRParen,
                     TypeContainsAuto);
}

ExprResult
Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
                  SourceLocation PlacementLParen,
                  MultiExprArg PlacementArgs,
                  SourceLocation PlacementRParen,
                  SourceRange TypeIdParens,
                  QualType AllocType,
                  TypeSourceInfo *AllocTypeInfo,
                  Expr *ArraySize,
                  SourceLocation ConstructorLParen,
                  MultiExprArg ConstructorArgs,
                  SourceLocation ConstructorRParen,
                  bool TypeMayContainAuto) {
  SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();

  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
  if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
    if (ConstructorArgs.size() == 0)
      return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
                       << AllocType << TypeRange);
    if (ConstructorArgs.size() != 1) {
      Expr *FirstBad = ConstructorArgs.get()[1];
      return ExprError(Diag(FirstBad->getSourceRange().getBegin(),
                            diag::err_auto_new_ctor_multiple_expressions)
                       << AllocType << TypeRange);
    }
    TypeSourceInfo *DeducedType = 0;
    if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType))
      return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
                       << AllocType
                       << ConstructorArgs.get()[0]->getType()
                       << TypeRange
                       << ConstructorArgs.get()[0]->getSourceRange());
    if (!DeducedType)
      return ExprError();

    AllocTypeInfo = DeducedType;
    AllocType = AllocTypeInfo->getType();
  }
  
  // Per C++0x [expr.new]p5, the type being constructed may be a
  // typedef of an array type.
  if (!ArraySize) {
    if (const ConstantArrayType *Array
                              = Context.getAsConstantArrayType(AllocType)) {
      ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
                                         Context.getSizeType(),
                                         TypeRange.getEnd());
      AllocType = Array->getElementType();
    }
  }

  if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
    return ExprError();

  // In ARC, infer 'retaining' for the allocated 
  if (getLangOptions().ObjCAutoRefCount &&
      AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
      AllocType->isObjCLifetimeType()) {
    AllocType = Context.getLifetimeQualifiedType(AllocType,
                                    AllocType->getObjCARCImplicitLifetime());
  }

  QualType ResultType = Context.getPointerType(AllocType);
    
  // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
  //   or enumeration type with a non-negative value."
  if (ArraySize && !ArraySize->isTypeDependent()) {
    // Eliminate placeholders.
    ExprResult ConvertedSize = CheckPlaceholderExpr(ArraySize);
    if (ConvertedSize.isInvalid())
      return ExprError();
    ArraySize = ConvertedSize.take();

    ConvertedSize = ConvertToIntegralOrEnumerationType(
      StartLoc, ArraySize,
      PDiag(diag::err_array_size_not_integral),
      PDiag(diag::err_array_size_incomplete_type)
        << ArraySize->getSourceRange(),
      PDiag(diag::err_array_size_explicit_conversion),
      PDiag(diag::note_array_size_conversion),
      PDiag(diag::err_array_size_ambiguous_conversion),
      PDiag(diag::note_array_size_conversion),
      PDiag(getLangOptions().CPlusPlus0x ?
              diag::warn_cxx98_compat_array_size_conversion :
              diag::ext_array_size_conversion));
    if (ConvertedSize.isInvalid())
      return ExprError();

    ArraySize = ConvertedSize.take();
    QualType SizeType = ArraySize->getType();
    if (!SizeType->isIntegralOrUnscopedEnumerationType())
      return ExprError();

    // Let's see if this is a constant < 0. If so, we reject it out of hand.
    // We don't care about special rules, so we tell the machinery it's not
    // evaluated - it gives us a result in more cases.
    if (!ArraySize->isValueDependent()) {
      llvm::APSInt Value;
      if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
        if (Value < llvm::APSInt(
                        llvm::APInt::getNullValue(Value.getBitWidth()),
                                 Value.isUnsigned()))
          return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
                                diag::err_typecheck_negative_array_size)
            << ArraySize->getSourceRange());

        if (!AllocType->isDependentType()) {
          unsigned ActiveSizeBits
            = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
          if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
            Diag(ArraySize->getSourceRange().getBegin(),
                 diag::err_array_too_large)
              << Value.toString(10)
              << ArraySize->getSourceRange();
            return ExprError();
          }
        }
      } else if (TypeIdParens.isValid()) {
        // Can't have dynamic array size when the type-id is in parentheses.
        Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
          << ArraySize->getSourceRange()
          << FixItHint::CreateRemoval(TypeIdParens.getBegin())
          << FixItHint::CreateRemoval(TypeIdParens.getEnd());

        TypeIdParens = SourceRange();
      }
    }

    // ARC: warn about ABI issues.
    if (getLangOptions().ObjCAutoRefCount) {
      QualType BaseAllocType = Context.getBaseElementType(AllocType);
      if (BaseAllocType.hasStrongOrWeakObjCLifetime())
        Diag(StartLoc, diag::warn_err_new_delete_object_array)
          << 0 << BaseAllocType;
    }

    // Note that we do *not* convert the argument in any way.  It can
    // be signed, larger than size_t, whatever.
  }

  FunctionDecl *OperatorNew = 0;
  FunctionDecl *OperatorDelete = 0;
  Expr **PlaceArgs = (Expr**)PlacementArgs.get();
  unsigned NumPlaceArgs = PlacementArgs.size();

  if (!AllocType->isDependentType() &&
      !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&
      FindAllocationFunctions(StartLoc,
                              SourceRange(PlacementLParen, PlacementRParen),
                              UseGlobal, AllocType, ArraySize, PlaceArgs,
                              NumPlaceArgs, OperatorNew, OperatorDelete))
    return ExprError();

  // If this is an array allocation, compute whether the usual array
  // deallocation function for the type has a size_t parameter.
  bool UsualArrayDeleteWantsSize = false;
  if (ArraySize && !AllocType->isDependentType())
    UsualArrayDeleteWantsSize
      = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType);

  SmallVector<Expr *, 8> AllPlaceArgs;
  if (OperatorNew) {
    // Add default arguments, if any.
    const FunctionProtoType *Proto =
      OperatorNew->getType()->getAs<FunctionProtoType>();
    VariadicCallType CallType =
      Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;

    if (GatherArgumentsForCall(PlacementLParen, OperatorNew,
                               Proto, 1, PlaceArgs, NumPlaceArgs,
                               AllPlaceArgs, CallType))
      return ExprError();

    NumPlaceArgs = AllPlaceArgs.size();
    if (NumPlaceArgs > 0)
      PlaceArgs = &AllPlaceArgs[0];
  }

  bool Init = ConstructorLParen.isValid();
  // --- Choosing a constructor ---
  CXXConstructorDecl *Constructor = 0;
  bool HadMultipleCandidates = false;
  Expr **ConsArgs = (Expr**)ConstructorArgs.get();
  unsigned NumConsArgs = ConstructorArgs.size();
  ASTOwningVector<Expr*> ConvertedConstructorArgs(*this);

  // Array 'new' can't have any initializers.
  if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) {
    SourceRange InitRange(ConsArgs[0]->getLocStart(),
                          ConsArgs[NumConsArgs - 1]->getLocEnd());

    Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
    return ExprError();
  }

  if (!AllocType->isDependentType() &&
      !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
    // C++0x [expr.new]p15:
    //   A new-expression that creates an object of type T initializes that
    //   object as follows:
    InitializationKind Kind
    //     - If the new-initializer is omitted, the object is default-
    //       initialized (8.5); if no initialization is performed,
    //       the object has indeterminate value
      = !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
    //     - Otherwise, the new-initializer is interpreted according to the
    //       initialization rules of 8.5 for direct-initialization.
             : InitializationKind::CreateDirect(TypeRange.getBegin(),
                                                ConstructorLParen,
                                                ConstructorRParen);

    InitializedEntity Entity
      = InitializedEntity::InitializeNew(StartLoc, AllocType);
    InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
    ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
                                                move(ConstructorArgs));
    if (FullInit.isInvalid())
      return ExprError();

    // FullInit is our initializer; walk through it to determine if it's a
    // constructor call, which CXXNewExpr handles directly.
    if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
      if (CXXBindTemporaryExpr *Binder
            = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
        FullInitExpr = Binder->getSubExpr();
      if (CXXConstructExpr *Construct
                    = dyn_cast<CXXConstructExpr>(FullInitExpr)) {
        Constructor = Construct->getConstructor();
        HadMultipleCandidates = Construct->hadMultipleCandidates();
        for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
                                         AEnd = Construct->arg_end();
             A != AEnd; ++A)
          ConvertedConstructorArgs.push_back(*A);
      } else {
        // Take the converted initializer.
        ConvertedConstructorArgs.push_back(FullInit.release());
      }
    } else {
      // No initialization required.
    }

    // Take the converted arguments and use them for the new expression.
    NumConsArgs = ConvertedConstructorArgs.size();
    ConsArgs = (Expr **)ConvertedConstructorArgs.take();
  }

  // Mark the new and delete operators as referenced.
  if (OperatorNew)
    MarkDeclarationReferenced(StartLoc, OperatorNew);
  if (OperatorDelete)
    MarkDeclarationReferenced(StartLoc, OperatorDelete);

  // C++0x [expr.new]p17:
  //   If the new expression creates an array of objects of class type,
  //   access and ambiguity control are done for the destructor.
  if (ArraySize && Constructor) {
    if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) {
      MarkDeclarationReferenced(StartLoc, dtor);
      CheckDestructorAccess(StartLoc, dtor, 
                            PDiag(diag::err_access_dtor)
                              << Context.getBaseElementType(AllocType));
    }
  }

  PlacementArgs.release();
  ConstructorArgs.release();

  return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
                                        PlaceArgs, NumPlaceArgs, TypeIdParens,
                                        ArraySize, Constructor, Init,
                                        ConsArgs, NumConsArgs,
                                        HadMultipleCandidates,
                                        OperatorDelete,
                                        UsualArrayDeleteWantsSize,
                                        ResultType, AllocTypeInfo,
                                        StartLoc,
                                        Init ? ConstructorRParen :
                                               TypeRange.getEnd(),
                                        ConstructorLParen, ConstructorRParen));
}

/// CheckAllocatedType - Checks that a type is suitable as the allocated type
/// in a new-expression.
/// dimension off and stores the size expression in ArraySize.
bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
                              SourceRange R) {
  // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
  //   abstract class type or array thereof.
  if (AllocType->isFunctionType())
    return Diag(Loc, diag::err_bad_new_type)
      << AllocType << 0 << R;
  else if (AllocType->isReferenceType())
    return Diag(Loc, diag::err_bad_new_type)
      << AllocType << 1 << R;
  else if (!AllocType->isDependentType() &&
           RequireCompleteType(Loc, AllocType,
                               PDiag(diag::err_new_incomplete_type)
                                 << R))
    return true;
  else if (RequireNonAbstractType(Loc, AllocType,
                                  diag::err_allocation_of_abstract_type))
    return true;
  else if (AllocType->isVariablyModifiedType())
    return Diag(Loc, diag::err_variably_modified_new_type)
             << AllocType;
  else if (unsigned AddressSpace = AllocType.getAddressSpace())
    return Diag(Loc, diag::err_address_space_qualified_new)
      << AllocType.getUnqualifiedType() << AddressSpace;
  else if (getLangOptions().ObjCAutoRefCount) {
    if (const ArrayType *AT = Context.getAsArrayType(AllocType)) {
      QualType BaseAllocType = Context.getBaseElementType(AT);
      if (BaseAllocType.getObjCLifetime() == Qualifiers::OCL_None &&
          BaseAllocType->isObjCLifetimeType())
        return Diag(Loc, diag::err_arc_new_array_without_ownership)
          << BaseAllocType;
    }
  }
           
  return false;
}

/// \brief Determine whether the given function is a non-placement
/// deallocation function.
static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) {
  if (FD->isInvalidDecl())
    return false;

  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
    return Method->isUsualDeallocationFunction();

  return ((FD->getOverloadedOperator() == OO_Delete ||
           FD->getOverloadedOperator() == OO_Array_Delete) &&
          FD->getNumParams() == 1);
}

/// FindAllocationFunctions - Finds the overloads of operator new and delete
/// that are appropriate for the allocation.
bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
                                   bool UseGlobal, QualType AllocType,
                                   bool IsArray, Expr **PlaceArgs,
                                   unsigned NumPlaceArgs,
                                   FunctionDecl *&OperatorNew,
                                   FunctionDecl *&OperatorDelete) {
  // --- Choosing an allocation function ---
  // C++ 5.3.4p8 - 14 & 18
  // 1) If UseGlobal is true, only look in the global scope. Else, also look
  //   in the scope of the allocated class.
  // 2) If an array size is given, look for operator new[], else look for
  //   operator new.
  // 3) The first argument is always size_t. Append the arguments from the
  //   placement form.

  SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs);
  // We don't care about the actual value of this argument.
  // FIXME: Should the Sema create the expression and embed it in the syntax
  // tree? Or should the consumer just recalculate the value?
  IntegerLiteral Size(Context, llvm::APInt::getNullValue(
                      Context.getTargetInfo().getPointerWidth(0)),
                      Context.getSizeType(),
                      SourceLocation());
  AllocArgs[0] = &Size;
  std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1);

  // C++ [expr.new]p8:
  //   If the allocated type is a non-array type, the allocation
  //   function's name is operator new and the deallocation function's
  //   name is operator delete. If the allocated type is an array
  //   type, the allocation function's name is operator new[] and the
  //   deallocation function's name is operator delete[].
  DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
                                        IsArray ? OO_Array_New : OO_New);
  DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
                                        IsArray ? OO_Array_Delete : OO_Delete);

  QualType AllocElemType = Context.getBaseElementType(AllocType);

  if (AllocElemType->isRecordType() && !UseGlobal) {
    CXXRecordDecl *Record
      = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
                          AllocArgs.size(), Record, /*AllowMissing=*/true,
                          OperatorNew))
      return true;
  }
  if (!OperatorNew) {
    // Didn't find a member overload. Look for a global one.
    DeclareGlobalNewDelete();
    DeclContext *TUDecl = Context.getTranslationUnitDecl();
    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
                          AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
                          OperatorNew))
      return true;
  }

  // We don't need an operator delete if we're running under
  // -fno-exceptions.
  if (!getLangOptions().Exceptions) {
    OperatorDelete = 0;
    return false;
  }

  // FindAllocationOverload can change the passed in arguments, so we need to
  // copy them back.
  if (NumPlaceArgs > 0)
    std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs);

  // C++ [expr.new]p19:
  //
  //   If the new-expression begins with a unary :: operator, the
  //   deallocation function's name is looked up in the global
  //   scope. Otherwise, if the allocated type is a class type T or an
  //   array thereof, the deallocation function's name is looked up in
  //   the scope of T. If this lookup fails to find the name, or if
  //   the allocated type is not a class type or array thereof, the
  //   deallocation function's name is looked up in the global scope.
  LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
  if (AllocElemType->isRecordType() && !UseGlobal) {
    CXXRecordDecl *RD
      = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
    LookupQualifiedName(FoundDelete, RD);
  }
  if (FoundDelete.isAmbiguous())
    return true; // FIXME: clean up expressions?

  if (FoundDelete.empty()) {
    DeclareGlobalNewDelete();
    LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
  }

  FoundDelete.suppressDiagnostics();

  SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;

  // Whether we're looking for a placement operator delete is dictated
  // by whether we selected a placement operator new, not by whether
  // we had explicit placement arguments.  This matters for things like
  //   struct A { void *operator new(size_t, int = 0); ... };
  //   A *a = new A()
  bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1);

  if (isPlacementNew) {
    // C++ [expr.new]p20:
    //   A declaration of a placement deallocation function matches the
    //   declaration of a placement allocation function if it has the
    //   same number of parameters and, after parameter transformations
    //   (8.3.5), all parameter types except the first are
    //   identical. [...]
    //
    // To perform this comparison, we compute the function type that
    // the deallocation function should have, and use that type both
    // for template argument deduction and for comparison purposes.
    //
    // FIXME: this comparison should ignore CC and the like.
    QualType ExpectedFunctionType;
    {
      const FunctionProtoType *Proto
        = OperatorNew->getType()->getAs<FunctionProtoType>();

      SmallVector<QualType, 4> ArgTypes;
      ArgTypes.push_back(Context.VoidPtrTy);
      for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I)
        ArgTypes.push_back(Proto->getArgType(I));

      FunctionProtoType::ExtProtoInfo EPI;
      EPI.Variadic = Proto->isVariadic();

      ExpectedFunctionType
        = Context.getFunctionType(Context.VoidTy, ArgTypes.data(),
                                  ArgTypes.size(), EPI);
    }

    for (LookupResult::iterator D = FoundDelete.begin(),
                             DEnd = FoundDelete.end();
         D != DEnd; ++D) {
      FunctionDecl *Fn = 0;
      if (FunctionTemplateDecl *FnTmpl
            = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
        // Perform template argument deduction to try to match the
        // expected function type.
        TemplateDeductionInfo Info(Context, StartLoc);
        if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info))
          continue;
      } else
        Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());

      if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
        Matches.push_back(std::make_pair(D.getPair(), Fn));
    }
  } else {
    // C++ [expr.new]p20:
    //   [...] Any non-placement deallocation function matches a
    //   non-placement allocation function. [...]
    for (LookupResult::iterator D = FoundDelete.begin(),
                             DEnd = FoundDelete.end();
         D != DEnd; ++D) {
      if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
        if (isNonPlacementDeallocationFunction(Fn))
          Matches.push_back(std::make_pair(D.getPair(), Fn));
    }
  }

  // C++ [expr.new]p20:
  //   [...] If the lookup finds a single matching deallocation
  //   function, that function will be called; otherwise, no
  //   deallocation function will be called.
  if (Matches.size() == 1) {
    OperatorDelete = Matches[0].second;

    // C++0x [expr.new]p20:
    //   If the lookup finds the two-parameter form of a usual
    //   deallocation function (3.7.4.2) and that function, considered
    //   as a placement deallocation function, would have been
    //   selected as a match for the allocation function, the program
    //   is ill-formed.
    if (NumPlaceArgs && getLangOptions().CPlusPlus0x &&
        isNonPlacementDeallocationFunction(OperatorDelete)) {
      Diag(StartLoc, diag::err_placement_new_non_placement_delete)
        << SourceRange(PlaceArgs[0]->getLocStart(),
                       PlaceArgs[NumPlaceArgs - 1]->getLocEnd());
      Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
        << DeleteName;
    } else {
      CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
                            Matches[0].first);
    }
  }

  return false;
}

/// FindAllocationOverload - Find an fitting overload for the allocation
/// function in the specified scope.
bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
                                  DeclarationName Name, Expr** Args,
                                  unsigned NumArgs, DeclContext *Ctx,
                                  bool AllowMissing, FunctionDecl *&Operator,
                                  bool Diagnose) {
  LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
  LookupQualifiedName(R, Ctx);
  if (R.empty()) {
    if (AllowMissing || !Diagnose)
      return false;
    return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
      << Name << Range;
  }

  if (R.isAmbiguous())
    return true;

  R.suppressDiagnostics();

  OverloadCandidateSet Candidates(StartLoc);
  for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
       Alloc != AllocEnd; ++Alloc) {
    // Even member operator new/delete are implicitly treated as
    // static, so don't use AddMemberCandidate.
    NamedDecl *D = (*Alloc)->getUnderlyingDecl();

    if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
      AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
                                   /*ExplicitTemplateArgs=*/0, Args, NumArgs,
                                   Candidates,
                                   /*SuppressUserConversions=*/false);
      continue;
    }

    FunctionDecl *Fn = cast<FunctionDecl>(D);
    AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates,
                         /*SuppressUserConversions=*/false);
  }

  // Do the resolution.
  OverloadCandidateSet::iterator Best;
  switch (Candidates.BestViableFunction(*this, StartLoc, Best)) {
  case OR_Success: {
    // Got one!
    FunctionDecl *FnDecl = Best->Function;
    MarkDeclarationReferenced(StartLoc, FnDecl);
    // The first argument is size_t, and the first parameter must be size_t,
    // too. This is checked on declaration and can be assumed. (It can't be
    // asserted on, though, since invalid decls are left in there.)
    // Watch out for variadic allocator function.
    unsigned NumArgsInFnDecl = FnDecl->getNumParams();
    for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
      InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
                                                       FnDecl->getParamDecl(i));

      if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i])))
        return true;

      ExprResult Result
        = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));
      if (Result.isInvalid())
        return true;

      Args[i] = Result.takeAs<Expr>();
    }
    Operator = FnDecl;
    CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl,
                          Diagnose);
    return false;
  }

  case OR_No_Viable_Function:
    if (Diagnose) {
      Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
        << Name << Range;
      Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
    }
    return true;

  case OR_Ambiguous:
    if (Diagnose) {
      Diag(StartLoc, diag::err_ovl_ambiguous_call)
        << Name << Range;
      Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
    }
    return true;

  case OR_Deleted: {
    if (Diagnose) {
      Diag(StartLoc, diag::err_ovl_deleted_call)
        << Best->Function->isDeleted()
        << Name 
        << getDeletedOrUnavailableSuffix(Best->Function)
        << Range;
      Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
    }
    return true;
  }
  }
  llvm_unreachable("Unreachable, bad result from BestViableFunction");
}


/// DeclareGlobalNewDelete - Declare the global forms of operator new and
/// delete. These are:
/// @code
///   // C++03:
///   void* operator new(std::size_t) throw(std::bad_alloc);
///   void* operator new[](std::size_t) throw(std::bad_alloc);
///   void operator delete(void *) throw();
///   void operator delete[](void *) throw();
///   // C++0x:
///   void* operator new(std::size_t);
///   void* operator new[](std::size_t);
///   void operator delete(void *);
///   void operator delete[](void *);
/// @endcode
/// C++0x operator delete is implicitly noexcept.
/// Note that the placement and nothrow forms of new are *not* implicitly
/// declared. Their use requires including \<new\>.
void Sema::DeclareGlobalNewDelete() {
  if (GlobalNewDeleteDeclared)
    return;

  // C++ [basic.std.dynamic]p2:
  //   [...] The following allocation and deallocation functions (18.4) are
  //   implicitly declared in global scope in each translation unit of a
  //   program
  //
  //     C++03:
  //     void* operator new(std::size_t) throw(std::bad_alloc);
  //     void* operator new[](std::size_t) throw(std::bad_alloc);
  //     void  operator delete(void*) throw();
  //     void  operator delete[](void*) throw();
  //     C++0x:
  //     void* operator new(std::size_t);
  //     void* operator new[](std::size_t);
  //     void  operator delete(void*);
  //     void  operator delete[](void*);
  //
  //   These implicit declarations introduce only the function names operator
  //   new, operator new[], operator delete, operator delete[].
  //
  // Here, we need to refer to std::bad_alloc, so we will implicitly declare
  // "std" or "bad_alloc" as necessary to form the exception specification.
  // However, we do not make these implicit declarations visible to name
  // lookup.
  // Note that the C++0x versions of operator delete are deallocation functions,
  // and thus are implicitly noexcept.
  if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) {
    // The "std::bad_alloc" class has not yet been declared, so build it
    // implicitly.
    StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
                                        getOrCreateStdNamespace(),
                                        SourceLocation(), SourceLocation(),
                                      &PP.getIdentifierTable().get("bad_alloc"),
                                        0);
    getStdBadAlloc()->setImplicit(true);
  }

  GlobalNewDeleteDeclared = true;

  QualType VoidPtr = Context.getPointerType(Context.VoidTy);
  QualType SizeT = Context.getSizeType();
  bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew;

  DeclareGlobalAllocationFunction(
      Context.DeclarationNames.getCXXOperatorName(OO_New),
      VoidPtr, SizeT, AssumeSaneOperatorNew);
  DeclareGlobalAllocationFunction(
      Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
      VoidPtr, SizeT, AssumeSaneOperatorNew);
  DeclareGlobalAllocationFunction(
      Context.DeclarationNames.getCXXOperatorName(OO_Delete),
      Context.VoidTy, VoidPtr);
  DeclareGlobalAllocationFunction(
      Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
      Context.VoidTy, VoidPtr);
}

/// DeclareGlobalAllocationFunction - Declares a single implicit global
/// allocation function if it doesn't already exist.
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
                                           QualType Return, QualType Argument,
                                           bool AddMallocAttr) {
  DeclContext *GlobalCtx = Context.getTranslationUnitDecl();

  // Check if this function is already declared.
  {
    DeclContext::lookup_iterator Alloc, AllocEnd;
    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
         Alloc != AllocEnd; ++Alloc) {
      // Only look at non-template functions, as it is the predefined,
      // non-templated allocation function we are trying to declare here.
      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
        QualType InitialParamType =
          Context.getCanonicalType(
            Func->getParamDecl(0)->getType().getUnqualifiedType());
        // FIXME: Do we need to check for default arguments here?
        if (Func->getNumParams() == 1 && InitialParamType == Argument) {
          if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
            Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
          return;
        }
      }
    }
  }

  QualType BadAllocType;
  bool HasBadAllocExceptionSpec
    = (Name.getCXXOverloadedOperator() == OO_New ||
       Name.getCXXOverloadedOperator() == OO_Array_New);
  if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) {
    assert(StdBadAlloc && "Must have std::bad_alloc declared");
    BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
  }

  FunctionProtoType::ExtProtoInfo EPI;
  if (HasBadAllocExceptionSpec) {
    if (!getLangOptions().CPlusPlus0x) {
      EPI.ExceptionSpecType = EST_Dynamic;
      EPI.NumExceptions = 1;
      EPI.Exceptions = &BadAllocType;
    }
  } else {
    EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ?
                                EST_BasicNoexcept : EST_DynamicNone;
  }

  QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);
  FunctionDecl *Alloc =
    FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
                         SourceLocation(), Name,
                         FnType, /*TInfo=*/0, SC_None,
                         SC_None, false, true);
  Alloc->setImplicit();

  if (AddMallocAttr)
    Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));

  ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
                                           SourceLocation(), 0,
                                           Argument, /*TInfo=*/0,
                                           SC_None, SC_None, 0);
  Alloc->setParams(Param);

  // FIXME: Also add this declaration to the IdentifierResolver, but
  // make sure it is at the end of the chain to coincide with the
  // global scope.
  Context.getTranslationUnitDecl()->addDecl(Alloc);
}

bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
                                    DeclarationName Name,
                                    FunctionDecl* &Operator, bool Diagnose) {
  LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
  // Try to find operator delete/operator delete[] in class scope.
  LookupQualifiedName(Found, RD);

  if (Found.isAmbiguous())
    return true;

  Found.suppressDiagnostics();

  SmallVector<DeclAccessPair,4> Matches;
  for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
       F != FEnd; ++F) {
    NamedDecl *ND = (*F)->getUnderlyingDecl();

    // Ignore template operator delete members from the check for a usual
    // deallocation function.
    if (isa<FunctionTemplateDecl>(ND))
      continue;

    if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction())
      Matches.push_back(F.getPair());
  }

  // There's exactly one suitable operator;  pick it.
  if (Matches.size() == 1) {
    Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());

    if (Operator->isDeleted()) {
      if (Diagnose) {
        Diag(StartLoc, diag::err_deleted_function_use);
        Diag(Operator->getLocation(), diag::note_unavailable_here) << true;
      }
      return true;
    }

    CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
                          Matches[0], Diagnose);
    return false;

  // We found multiple suitable operators;  complain about the ambiguity.
  } else if (!Matches.empty()) {
    if (Diagnose) {
      Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
        << Name << RD;

      for (SmallVectorImpl<DeclAccessPair>::iterator
             F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
        Diag((*F)->getUnderlyingDecl()->getLocation(),
             diag::note_member_declared_here) << Name;
    }
    return true;
  }

  // We did find operator delete/operator delete[] declarations, but
  // none of them were suitable.
  if (!Found.empty()) {
    if (Diagnose) {
      Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
        << Name << RD;

      for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
           F != FEnd; ++F)
        Diag((*F)->getUnderlyingDecl()->getLocation(),
             diag::note_member_declared_here) << Name;
    }
    return true;
  }

  // Look for a global declaration.
  DeclareGlobalNewDelete();
  DeclContext *TUDecl = Context.getTranslationUnitDecl();

  CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
  Expr* DeallocArgs[1];
  DeallocArgs[0] = &Null;
  if (FindAllocationOverload(StartLoc, SourceRange(), Name,
                             DeallocArgs, 1, TUDecl, !Diagnose,
                             Operator, Diagnose))
    return true;

  assert(Operator && "Did not find a deallocation function!");
  return false;
}

/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
/// @code ::delete ptr; @endcode
/// or
/// @code delete [] ptr; @endcode
ExprResult
Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
                     bool ArrayForm, Expr *ExE) {
  // C++ [expr.delete]p1:
  //   The operand shall have a pointer type, or a class type having a single
  //   conversion function to a pointer type. The result has type void.
  //
  // DR599 amends "pointer type" to "pointer to object type" in both cases.

  ExprResult Ex = Owned(ExE);
  FunctionDecl *OperatorDelete = 0;
  bool ArrayFormAsWritten = ArrayForm;
  bool UsualArrayDeleteWantsSize = false;

  if (!Ex.get()->isTypeDependent()) {
    QualType Type = Ex.get()->getType();

    if (const RecordType *Record = Type->getAs<RecordType>()) {
      if (RequireCompleteType(StartLoc, Type,
                              PDiag(diag::err_delete_incomplete_class_type)))
        return ExprError();

      SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;

      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
      const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
             E = Conversions->end(); I != E; ++I) {
        NamedDecl *D = I.getDecl();
        if (isa<UsingShadowDecl>(D))
          D = cast<UsingShadowDecl>(D)->getTargetDecl();

        // Skip over templated conversion functions; they aren't considered.
        if (isa<FunctionTemplateDecl>(D))
          continue;

        CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);

        QualType ConvType = Conv->getConversionType().getNonReferenceType();
        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
            ObjectPtrConversions.push_back(Conv);
      }
      if (ObjectPtrConversions.size() == 1) {
        // We have a single conversion to a pointer-to-object type. Perform
        // that conversion.
        // TODO: don't redo the conversion calculation.
        ExprResult Res =
          PerformImplicitConversion(Ex.get(),
                            ObjectPtrConversions.front()->getConversionType(),
                                    AA_Converting);
        if (Res.isUsable()) {
          Ex = move(Res);
          Type = Ex.get()->getType();
        }
      }
      else if (ObjectPtrConversions.size() > 1) {
        Diag(StartLoc, diag::err_ambiguous_delete_operand)
              << Type << Ex.get()->getSourceRange();
        for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
          NoteOverloadCandidate(ObjectPtrConversions[i]);
        return ExprError();
      }
    }

    if (!Type->isPointerType())
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex.get()->getSourceRange());

    QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
    QualType PointeeElem = Context.getBaseElementType(Pointee);

    if (unsigned AddressSpace = Pointee.getAddressSpace())
      return Diag(Ex.get()->getLocStart(), 
                  diag::err_address_space_qualified_delete)
               << Pointee.getUnqualifiedType() << AddressSpace;

    CXXRecordDecl *PointeeRD = 0;
    if (Pointee->isVoidType() && !isSFINAEContext()) {
      // The C++ standard bans deleting a pointer to a non-object type, which
      // effectively bans deletion of "void*". However, most compilers support
      // this, so we treat it as a warning unless we're in a SFINAE context.
      Diag(StartLoc, diag::ext_delete_void_ptr_operand)
        << Type << Ex.get()->getSourceRange();
    } else if (Pointee->isFunctionType() || Pointee->isVoidType()) {
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex.get()->getSourceRange());
    } else if (!Pointee->isDependentType()) {
      if (!RequireCompleteType(StartLoc, Pointee,
                               PDiag(diag::warn_delete_incomplete)
                                 << Ex.get()->getSourceRange())) {
        if (const RecordType *RT = PointeeElem->getAs<RecordType>())
          PointeeRD = cast<CXXRecordDecl>(RT->getDecl());
      }
    }

    // Perform lvalue-to-rvalue cast, if needed.
    Ex = DefaultLvalueConversion(Ex.take());

    // C++ [expr.delete]p2:
    //   [Note: a pointer to a const type can be the operand of a
    //   delete-expression; it is not necessary to cast away the constness
    //   (5.2.11) of the pointer expression before it is used as the operand
    //   of the delete-expression. ]
    if (!Context.hasSameType(Ex.get()->getType(), Context.VoidPtrTy))
      Ex = Owned(ImplicitCastExpr::Create(Context, Context.VoidPtrTy,
                                          CK_BitCast, Ex.take(), 0, VK_RValue));

    if (Pointee->isArrayType() && !ArrayForm) {
      Diag(StartLoc, diag::warn_delete_array_type)
          << Type << Ex.get()->getSourceRange()
          << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
      ArrayForm = true;
    }

    DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
                                      ArrayForm ? OO_Array_Delete : OO_Delete);

    if (PointeeRD) {
      if (!UseGlobal &&
          FindDeallocationFunction(StartLoc, PointeeRD, DeleteName,
                                   OperatorDelete))
        return ExprError();

      // If we're allocating an array of records, check whether the
      // usual operator delete[] has a size_t parameter.
      if (ArrayForm) {
        // If the user specifically asked to use the global allocator,
        // we'll need to do the lookup into the class.
        if (UseGlobal)
          UsualArrayDeleteWantsSize =
            doesUsualArrayDeleteWantSize(*this, StartLoc, PointeeElem);

        // Otherwise, the usual operator delete[] should be the
        // function we just found.
        else if (isa<CXXMethodDecl>(OperatorDelete))
          UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
      }

      if (!PointeeRD->hasTrivialDestructor())
        if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
          MarkDeclarationReferenced(StartLoc,
                                    const_cast<CXXDestructorDecl*>(Dtor));
          DiagnoseUseOfDecl(Dtor, StartLoc);
        }

      // C++ [expr.delete]p3:
      //   In the first alternative (delete object), if the static type of the
      //   object to be deleted is different from its dynamic type, the static
      //   type shall be a base class of the dynamic type of the object to be
      //   deleted and the static type shall have a virtual destructor or the
      //   behavior is undefined.
      //
      // Note: a final class cannot be derived from, no issue there
      if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr<FinalAttr>()) {
        CXXDestructorDecl *dtor = PointeeRD->getDestructor();
        if (dtor && !dtor->isVirtual()) {
          if (PointeeRD->isAbstract()) {
            // If the class is abstract, we warn by default, because we're
            // sure the code has undefined behavior.
            Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor)
                << PointeeElem;
          } else if (!ArrayForm) {
            // Otherwise, if this is not an array delete, it's a bit suspect,
            // but not necessarily wrong.
            Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
          }
        }
      }

    } else if (getLangOptions().ObjCAutoRefCount &&
               PointeeElem->isObjCLifetimeType() &&
               (PointeeElem.getObjCLifetime() == Qualifiers::OCL_Strong ||
                PointeeElem.getObjCLifetime() == Qualifiers::OCL_Weak) &&
               ArrayForm) {
      Diag(StartLoc, diag::warn_err_new_delete_object_array)
        << 1 << PointeeElem;
    }

    if (!OperatorDelete) {
      // Look for a global declaration.
      DeclareGlobalNewDelete();
      DeclContext *TUDecl = Context.getTranslationUnitDecl();
      Expr *Arg = Ex.get();
      if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
                                 &Arg, 1, TUDecl, /*AllowMissing=*/false,
                                 OperatorDelete))
        return ExprError();
    }

    MarkDeclarationReferenced(StartLoc, OperatorDelete);
    
    // Check access and ambiguity of operator delete and destructor.
    if (PointeeRD) {
      if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
          CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, 
                      PDiag(diag::err_access_dtor) << PointeeElem);
      }
    }

  }

  return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
                                           ArrayFormAsWritten,
                                           UsualArrayDeleteWantsSize,
                                           OperatorDelete, Ex.take(), StartLoc));
}

/// \brief Check the use of the given variable as a C++ condition in an if,
/// while, do-while, or switch statement.
ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
                                        SourceLocation StmtLoc,
                                        bool ConvertToBoolean) {
  QualType T = ConditionVar->getType();

  // C++ [stmt.select]p2:
  //   The declarator shall not specify a function or an array.
  if (T->isFunctionType())
    return ExprError(Diag(ConditionVar->getLocation(),
                          diag::err_invalid_use_of_function_type)
                       << ConditionVar->getSourceRange());
  else if (T->isArrayType())
    return ExprError(Diag(ConditionVar->getLocation(),
                          diag::err_invalid_use_of_array_type)
                     << ConditionVar->getSourceRange());

  ExprResult Condition =
    Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), 
                                        ConditionVar,
                                        ConditionVar->getLocation(),
                            ConditionVar->getType().getNonReferenceType(),
                              VK_LValue));
  if (ConvertToBoolean) {
    Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
    if (Condition.isInvalid())
      return ExprError();
  }

  return move(Condition);
}

/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) {
  // C++ 6.4p4:
  // The value of a condition that is an initialized declaration in a statement
  // other than a switch statement is the value of the declared variable
  // implicitly converted to type bool. If that conversion is ill-formed, the
  // program is ill-formed.
  // The value of a condition that is an expression is the value of the
  // expression, implicitly converted to bool.
  //
  return PerformContextuallyConvertToBool(CondExpr);
}

/// Helper function to determine whether this is the (deprecated) C++
/// conversion from a string literal to a pointer to non-const char or
/// non-const wchar_t (for narrow and wide string literals,
/// respectively).
bool
Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
  // Look inside the implicit cast, if it exists.
  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(From))
    From = Cast->getSubExpr();

  // A string literal (2.13.4) that is not a wide string literal can
  // be converted to an rvalue of type "pointer to char"; a wide
  // string literal can be converted to an rvalue of type "pointer
  // to wchar_t" (C++ 4.2p2).
  if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens()))
    if (const PointerType *ToPtrType = ToType->getAs<PointerType>())
      if (const BuiltinType *ToPointeeType
          = ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
        // This conversion is considered only when there is an
        // explicit appropriate pointer target type (C++ 4.2p2).
        if (!ToPtrType->getPointeeType().hasQualifiers()) {
          switch (StrLit->getKind()) {
            case StringLiteral::UTF8:
            case StringLiteral::UTF16:
            case StringLiteral::UTF32:
              // We don't allow UTF literals to be implicitly converted
              break;
            case StringLiteral::Ascii:
              return (ToPointeeType->getKind() == BuiltinType::Char_U ||
                      ToPointeeType->getKind() == BuiltinType::Char_S);
            case StringLiteral::Wide:
              return ToPointeeType->isWideCharType();
          }
        }
      }

  return false;
}

static ExprResult BuildCXXCastArgument(Sema &S,
                                       SourceLocation CastLoc,
                                       QualType Ty,
                                       CastKind Kind,
                                       CXXMethodDecl *Method,
                                       DeclAccessPair FoundDecl,
                                       bool HadMultipleCandidates,
                                       Expr *From) {
  switch (Kind) {
  default: llvm_unreachable("Unhandled cast kind!");
  case CK_ConstructorConversion: {
    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Method);
    ASTOwningVector<Expr*> ConstructorArgs(S);

    if (S.CompleteConstructorCall(Constructor,
                                  MultiExprArg(&From, 1),
                                  CastLoc, ConstructorArgs))
      return ExprError();

    S.CheckConstructorAccess(CastLoc, Constructor, Constructor->getAccess(),
                             S.PDiag(diag::err_access_ctor));
    
    ExprResult Result
      = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
                                move_arg(ConstructorArgs), 
                                HadMultipleCandidates, /*ZeroInit*/ false, 
                                CXXConstructExpr::CK_Complete, SourceRange());
    if (Result.isInvalid())
      return ExprError();

    return S.MaybeBindToTemporary(Result.takeAs<Expr>());
  }

  case CK_UserDefinedConversion: {
    assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");

    // Create an implicit call expr that calls it.
    ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method,
                                                 HadMultipleCandidates);
    if (Result.isInvalid())
      return ExprError();
    // Record usage of conversion in an implicit cast.
    Result = S.Owned(ImplicitCastExpr::Create(S.Context,
                                              Result.get()->getType(),
                                              CK_UserDefinedConversion,
                                              Result.get(), 0,
                                              Result.get()->getValueKind()));

    S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl);

    return S.MaybeBindToTemporary(Result.get());
  }
  }
}

/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType using the pre-computed implicit
/// conversion sequence ICS. Returns the converted
/// expression. Action is the kind of conversion we're performing,
/// used in the error message.
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
                                const ImplicitConversionSequence &ICS,
                                AssignmentAction Action, 
                                CheckedConversionKind CCK) {
  switch (ICS.getKind()) {
  case ImplicitConversionSequence::StandardConversion: {
    ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard,
                                               Action, CCK);
    if (Res.isInvalid())
      return ExprError();
    From = Res.take();
    break;
  }

  case ImplicitConversionSequence::UserDefinedConversion: {

      FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
      CastKind CastKind;
      QualType BeforeToType;
      assert(FD && "FIXME: aggregate initialization from init list");
      if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
        CastKind = CK_UserDefinedConversion;

        // If the user-defined conversion is specified by a conversion function,
        // the initial standard conversion sequence converts the source type to
        // the implicit object parameter of the conversion function.
        BeforeToType = Context.getTagDeclType(Conv->getParent());
      } else {
        const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD);
        CastKind = CK_ConstructorConversion;
        // Do no conversion if dealing with ... for the first conversion.
        if (!ICS.UserDefined.EllipsisConversion) {
          // If the user-defined conversion is specified by a constructor, the
          // initial standard conversion sequence converts the source type to the
          // type required by the argument of the constructor
          BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
        }
      }
      // Watch out for elipsis conversion.
      if (!ICS.UserDefined.EllipsisConversion) {
        ExprResult Res =
          PerformImplicitConversion(From, BeforeToType,
                                    ICS.UserDefined.Before, AA_Converting,
                                    CCK);
        if (Res.isInvalid())
          return ExprError();
        From = Res.take();
      }

      ExprResult CastArg
        = BuildCXXCastArgument(*this,
                               From->getLocStart(),
                               ToType.getNonReferenceType(),
                               CastKind, cast<CXXMethodDecl>(FD),
                               ICS.UserDefined.FoundConversionFunction,
                               ICS.UserDefined.HadMultipleCandidates,
                               From);

      if (CastArg.isInvalid())
        return ExprError();

      From = CastArg.take();

      return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
                                       AA_Converting, CCK);
  }

  case ImplicitConversionSequence::AmbiguousConversion:
    ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
                          PDiag(diag::err_typecheck_ambiguous_condition)
                            << From->getSourceRange());
     return ExprError();

  case ImplicitConversionSequence::EllipsisConversion:
    llvm_unreachable("Cannot perform an ellipsis conversion");

  case ImplicitConversionSequence::BadConversion:
    return ExprError();
  }

  // Everything went well.
  return Owned(From);
}

/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType by following the standard
/// conversion sequence SCS. Returns the converted
/// expression. Flavor is the context in which we're performing this
/// conversion, for use in error messages.
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
                                const StandardConversionSequence& SCS,
                                AssignmentAction Action, 
                                CheckedConversionKind CCK) {
  bool CStyle = (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast);
  
  // Overall FIXME: we are recomputing too many types here and doing far too
  // much extra work. What this means is that we need to keep track of more
  // information that is computed when we try the implicit conversion initially,
  // so that we don't need to recompute anything here.
  QualType FromType = From->getType();
  
  if (SCS.CopyConstructor) {
    // FIXME: When can ToType be a reference type?
    assert(!ToType->isReferenceType());
    if (SCS.Second == ICK_Derived_To_Base) {
      ASTOwningVector<Expr*> ConstructorArgs(*this);
      if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
                                  MultiExprArg(*this, &From, 1),
                                  /*FIXME:ConstructLoc*/SourceLocation(),
                                  ConstructorArgs))
        return ExprError();
      return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
                                   ToType, SCS.CopyConstructor,
                                   move_arg(ConstructorArgs),
                                   /*HadMultipleCandidates*/ false,
                                   /*ZeroInit*/ false,
                                   CXXConstructExpr::CK_Complete,
                                   SourceRange());
    }
    return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
                                 ToType, SCS.CopyConstructor,
                                 MultiExprArg(*this, &From, 1),
                                 /*HadMultipleCandidates*/ false,
                                 /*ZeroInit*/ false,
                                 CXXConstructExpr::CK_Complete,
                                 SourceRange());
  }

  // Resolve overloaded function references.
  if (Context.hasSameType(FromType, Context.OverloadTy)) {
    DeclAccessPair Found;
    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
                                                          true, Found);
    if (!Fn)
      return ExprError();

    if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
      return ExprError();

    From = FixOverloadedFunctionReference(From, Found, Fn);
    FromType = From->getType();
  }

  // Perform the first implicit conversion.
  switch (SCS.First) {
  case ICK_Identity:
    // Nothing to do.
    break;

  case ICK_Lvalue_To_Rvalue:
    assert(From->getObjectKind() != OK_ObjCProperty);
    FromType = FromType.getUnqualifiedType();
    From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue,
                                    From, 0, VK_RValue);
    break;

  case ICK_Array_To_Pointer:
    FromType = Context.getArrayDecayedType(FromType);
    From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Function_To_Pointer:
    FromType = Context.getPointerType(FromType);
    From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  default:
    llvm_unreachable("Improper first standard conversion");
  }

  // Perform the second implicit conversion
  switch (SCS.Second) {
  case ICK_Identity:
    // If both sides are functions (or pointers/references to them), there could
    // be incompatible exception declarations.
    if (CheckExceptionSpecCompatibility(From, ToType))
      return ExprError();
    // Nothing else to do.
    break;

  case ICK_NoReturn_Adjustment:
    // If both sides are functions (or pointers/references to them), there could
    // be incompatible exception declarations.
    if (CheckExceptionSpecCompatibility(From, ToType))
      return ExprError();

    From = ImpCastExprToType(From, ToType, CK_NoOp, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Integral_Promotion:
  case ICK_Integral_Conversion:
    From = ImpCastExprToType(From, ToType, CK_IntegralCast, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Floating_Promotion:
  case ICK_Floating_Conversion:
    From = ImpCastExprToType(From, ToType, CK_FloatingCast, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Complex_Promotion:
  case ICK_Complex_Conversion: {
    QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType();
    QualType ToEl = ToType->getAs<ComplexType>()->getElementType();
    CastKind CK;
    if (FromEl->isRealFloatingType()) {
      if (ToEl->isRealFloatingType())
        CK = CK_FloatingComplexCast;
      else
        CK = CK_FloatingComplexToIntegralComplex;
    } else if (ToEl->isRealFloatingType()) {
      CK = CK_IntegralComplexToFloatingComplex;
    } else {
      CK = CK_IntegralComplexCast;
    }
    From = ImpCastExprToType(From, ToType, CK, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;
  }

  case ICK_Floating_Integral:
    if (ToType->isRealFloatingType())
      From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, 
                               VK_RValue, /*BasePath=*/0, CCK).take();
    else
      From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, 
                               VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Compatible_Conversion:
      From = ImpCastExprToType(From, ToType, CK_NoOp, 
                               VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Writeback_Conversion:
  case ICK_Pointer_Conversion: {
    if (SCS.IncompatibleObjC && Action != AA_Casting) {
      // Diagnose incompatible Objective-C conversions
      if (Action == AA_Initializing || Action == AA_Assigning)
        Diag(From->getSourceRange().getBegin(),
             diag::ext_typecheck_convert_incompatible_pointer)
          << ToType << From->getType() << Action
          << From->getSourceRange() << 0;
      else
        Diag(From->getSourceRange().getBegin(),
             diag::ext_typecheck_convert_incompatible_pointer)
          << From->getType() << ToType << Action
          << From->getSourceRange() << 0;

      if (From->getType()->isObjCObjectPointerType() &&
          ToType->isObjCObjectPointerType())
        EmitRelatedResultTypeNote(From);
    } 
    else if (getLangOptions().ObjCAutoRefCount &&
             !CheckObjCARCUnavailableWeakConversion(ToType, 
                                                    From->getType())) {
      if (Action == AA_Initializing)
        Diag(From->getSourceRange().getBegin(), 
             diag::err_arc_weak_unavailable_assign);
      else
        Diag(From->getSourceRange().getBegin(),
             diag::err_arc_convesion_of_weak_unavailable) 
          << (Action == AA_Casting) << From->getType() << ToType 
          << From->getSourceRange();
    }
             
    CastKind Kind = CK_Invalid;
    CXXCastPath BasePath;
    if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
      return ExprError();

    // Make sure we extend blocks if necessary.
    // FIXME: doing this here is really ugly.
    if (Kind == CK_BlockPointerToObjCPointerCast) {
      ExprResult E = From;
      (void) PrepareCastToObjCObjectPointer(E);
      From = E.take();
    }

    From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
             .take();
    break;
  }

  case ICK_Pointer_Member: {
    CastKind Kind = CK_Invalid;
    CXXCastPath BasePath;
    if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle))
      return ExprError();
    if (CheckExceptionSpecCompatibility(From, ToType))
      return ExprError();
    From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
             .take();
    break;
  }

  case ICK_Boolean_Conversion:
    // Perform half-to-boolean conversion via float.
    if (From->getType()->isHalfType()) {
      From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take();
      FromType = Context.FloatTy;
    }

    From = ImpCastExprToType(From, Context.BoolTy,
                             ScalarTypeToBooleanCastKind(FromType), 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Derived_To_Base: {
    CXXCastPath BasePath;
    if (CheckDerivedToBaseConversion(From->getType(),
                                     ToType.getNonReferenceType(),
                                     From->getLocStart(),
                                     From->getSourceRange(),
                                     &BasePath,
                                     CStyle))
      return ExprError();

    From = ImpCastExprToType(From, ToType.getNonReferenceType(),
                      CK_DerivedToBase, From->getValueKind(),
                      &BasePath, CCK).take();
    break;
  }

  case ICK_Vector_Conversion:
    From = ImpCastExprToType(From, ToType, CK_BitCast, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Vector_Splat:
    From = ImpCastExprToType(From, ToType, CK_VectorSplat, 
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;

  case ICK_Complex_Real:
    // Case 1.  x -> _Complex y
    if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) {
      QualType ElType = ToComplex->getElementType();
      bool isFloatingComplex = ElType->isRealFloatingType();

      // x -> y
      if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
        // do nothing
      } else if (From->getType()->isRealFloatingType()) {
        From = ImpCastExprToType(From, ElType,
                isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take();
      } else {
        assert(From->getType()->isIntegerType());
        From = ImpCastExprToType(From, ElType,
                isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take();
      }
      // y -> _Complex y
      From = ImpCastExprToType(From, ToType,
                   isFloatingComplex ? CK_FloatingRealToComplex
                                     : CK_IntegralRealToComplex).take();

    // Case 2.  _Complex x -> y
    } else {
      const ComplexType *FromComplex = From->getType()->getAs<ComplexType>();
      assert(FromComplex);

      QualType ElType = FromComplex->getElementType();
      bool isFloatingComplex = ElType->isRealFloatingType();

      // _Complex x -> x
      From = ImpCastExprToType(From, ElType,
                   isFloatingComplex ? CK_FloatingComplexToReal
                                     : CK_IntegralComplexToReal, 
                               VK_RValue, /*BasePath=*/0, CCK).take();

      // x -> y
      if (Context.hasSameUnqualifiedType(ElType, ToType)) {
        // do nothing
      } else if (ToType->isRealFloatingType()) {
        From = ImpCastExprToType(From, ToType,
                   isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating, 
                                 VK_RValue, /*BasePath=*/0, CCK).take();
      } else {
        assert(ToType->isIntegerType());
        From = ImpCastExprToType(From, ToType,
                   isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast, 
                                 VK_RValue, /*BasePath=*/0, CCK).take();
      }
    }
    break;
  
  case ICK_Block_Pointer_Conversion: {
    From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
                             VK_RValue, /*BasePath=*/0, CCK).take();
    break;
  }
      
  case ICK_TransparentUnionConversion: {
    ExprResult FromRes = Owned(From);
    Sema::AssignConvertType ConvTy =
      CheckTransparentUnionArgumentConstraints(ToType, FromRes);
    if (FromRes.isInvalid())
      return ExprError();
    From = FromRes.take();
    assert ((ConvTy == Sema::Compatible) &&
            "Improper transparent union conversion");
    (void)ConvTy;
    break;
  }

  case ICK_Lvalue_To_Rvalue:
  case ICK_Array_To_Pointer:
  case ICK_Function_To_Pointer:
  case ICK_Qualification:
  case ICK_Num_Conversion_Kinds:
    llvm_unreachable("Improper second standard conversion");
  }

  switch (SCS.Third) {
  case ICK_Identity:
    // Nothing to do.
    break;

  case ICK_Qualification: {
    // The qualification keeps the category of the inner expression, unless the
    // target type isn't a reference.
    ExprValueKind VK = ToType->isReferenceType() ?
                                  From->getValueKind() : VK_RValue;
    From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
                             CK_NoOp, VK, /*BasePath=*/0, CCK).take();

    if (SCS.DeprecatedStringLiteralToCharPtr &&
        !getLangOptions().WritableStrings)
      Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
        << ToType.getNonReferenceType();

    break;
    }

  default:
    llvm_unreachable("Improper third standard conversion");
  }

  return Owned(From);
}

ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
                                     SourceLocation KWLoc,
                                     ParsedType Ty,
                                     SourceLocation RParen) {
  TypeSourceInfo *TSInfo;
  QualType T = GetTypeFromParser(Ty, &TSInfo);

  if (!TSInfo)
    TSInfo = Context.getTrivialTypeSourceInfo(T);
  return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
}

/// \brief Check the completeness of a type in a unary type trait.
///
/// If the particular type trait requires a complete type, tries to complete
/// it. If completing the type fails, a diagnostic is emitted and false
/// returned. If completing the type succeeds or no completion was required,
/// returns true.
static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
                                                UnaryTypeTrait UTT,
                                                SourceLocation Loc,
                                                QualType ArgTy) {
  // C++0x [meta.unary.prop]p3:
  //   For all of the class templates X declared in this Clause, instantiating
  //   that template with a template argument that is a class template
  //   specialization may result in the implicit instantiation of the template
  //   argument if and only if the semantics of X require that the argument
  //   must be a complete type.
  // We apply this rule to all the type trait expressions used to implement
  // these class templates. We also try to follow any GCC documented behavior
  // in these expressions to ensure portability of standard libraries.
  switch (UTT) {
    // is_complete_type somewhat obviously cannot require a complete type.
  case UTT_IsCompleteType:
    // Fall-through

    // These traits are modeled on the type predicates in C++0x
    // [meta.unary.cat] and [meta.unary.comp]. They are not specified as
    // requiring a complete type, as whether or not they return true cannot be
    // impacted by the completeness of the type.
  case UTT_IsVoid:
  case UTT_IsIntegral:
  case UTT_IsFloatingPoint:
  case UTT_IsArray:
  case UTT_IsPointer:
  case UTT_IsLvalueReference:
  case UTT_IsRvalueReference:
  case UTT_IsMemberFunctionPointer:
  case UTT_IsMemberObjectPointer:
  case UTT_IsEnum:
  case UTT_IsUnion:
  case UTT_IsClass:
  case UTT_IsFunction:
  case UTT_IsReference:
  case UTT_IsArithmetic:
  case UTT_IsFundamental:
  case UTT_IsObject:
  case UTT_IsScalar:
  case UTT_IsCompound:
  case UTT_IsMemberPointer:
    // Fall-through

    // These traits are modeled on type predicates in C++0x [meta.unary.prop]
    // which requires some of its traits to have the complete type. However,
    // the completeness of the type cannot impact these traits' semantics, and
    // so they don't require it. This matches the comments on these traits in
    // Table 49.
  case UTT_IsConst:
  case UTT_IsVolatile:
  case UTT_IsSigned:
  case UTT_IsUnsigned:
    return true;

    // C++0x [meta.unary.prop] Table 49 requires the following traits to be
    // applied to a complete type.
  case UTT_IsTrivial:
  case UTT_IsTriviallyCopyable:
  case UTT_IsStandardLayout:
  case UTT_IsPOD:
  case UTT_IsLiteral:
  case UTT_IsEmpty:
  case UTT_IsPolymorphic:
  case UTT_IsAbstract:
    // Fall-through

  // These traits require a complete type.
  case UTT_IsFinal:

    // These trait expressions are designed to help implement predicates in
    // [meta.unary.prop] despite not being named the same. They are specified
    // by both GCC and the Embarcadero C++ compiler, and require the complete
    // type due to the overarching C++0x type predicates being implemented
    // requiring the complete type.
  case UTT_HasNothrowAssign:
  case UTT_HasNothrowConstructor:
  case UTT_HasNothrowCopy:
  case UTT_HasTrivialAssign:
  case UTT_HasTrivialDefaultConstructor:
  case UTT_HasTrivialCopy:
  case UTT_HasTrivialDestructor:
  case UTT_HasVirtualDestructor:
    // Arrays of unknown bound are expressly allowed.
    QualType ElTy = ArgTy;
    if (ArgTy->isIncompleteArrayType())
      ElTy = S.Context.getAsArrayType(ArgTy)->getElementType();

    // The void type is expressly allowed.
    if (ElTy->isVoidType())
      return true;

    return !S.RequireCompleteType(
      Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
  }
  llvm_unreachable("Type trait not handled by switch");
}

static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
                                   SourceLocation KeyLoc, QualType T) {
  assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");

  ASTContext &C = Self.Context;
  switch(UTT) {
    // Type trait expressions corresponding to the primary type category
    // predicates in C++0x [meta.unary.cat].
  case UTT_IsVoid:
    return T->isVoidType();
  case UTT_IsIntegral:
    return T->isIntegralType(C);
  case UTT_IsFloatingPoint:
    return T->isFloatingType();
  case UTT_IsArray:
    return T->isArrayType();
  case UTT_IsPointer:
    return T->isPointerType();
  case UTT_IsLvalueReference:
    return T->isLValueReferenceType();
  case UTT_IsRvalueReference:
    return T->isRValueReferenceType();
  case UTT_IsMemberFunctionPointer:
    return T->isMemberFunctionPointerType();
  case UTT_IsMemberObjectPointer:
    return T->isMemberDataPointerType();
  case UTT_IsEnum:
    return T->isEnumeralType();
  case UTT_IsUnion:
    return T->isUnionType();
  case UTT_IsClass:
    return T->isClassType() || T->isStructureType();
  case UTT_IsFunction:
    return T->isFunctionType();

    // Type trait expressions which correspond to the convenient composition
    // predicates in C++0x [meta.unary.comp].
  case UTT_IsReference:
    return T->isReferenceType();
  case UTT_IsArithmetic:
    return T->isArithmeticType() && !T->isEnumeralType();
  case UTT_IsFundamental:
    return T->isFundamentalType();
  case UTT_IsObject:
    return T->isObjectType();
  case UTT_IsScalar:
    // Note: semantic analysis depends on Objective-C lifetime types to be
    // considered scalar types. However, such types do not actually behave
    // like scalar types at run time (since they may require retain/release
    // operations), so we report them as non-scalar.
    if (T->isObjCLifetimeType()) {
      switch (T.getObjCLifetime()) {
      case Qualifiers::OCL_None:
      case Qualifiers::OCL_ExplicitNone:
        return true;

      case Qualifiers::OCL_Strong:
      case Qualifiers::OCL_Weak:
      case Qualifiers::OCL_Autoreleasing:
        return false;
      }
    }
      
    return T->isScalarType();
  case UTT_IsCompound:
    return T->isCompoundType();
  case UTT_IsMemberPointer:
    return T->isMemberPointerType();

    // Type trait expressions which correspond to the type property predicates
    // in C++0x [meta.unary.prop].
  case UTT_IsConst:
    return T.isConstQualified();
  case UTT_IsVolatile:
    return T.isVolatileQualified();
  case UTT_IsTrivial:
    return T.isTrivialType(Self.Context);
  case UTT_IsTriviallyCopyable:
    return T.isTriviallyCopyableType(Self.Context);
  case UTT_IsStandardLayout:
    return T->isStandardLayoutType();
  case UTT_IsPOD:
    return T.isPODType(Self.Context);
  case UTT_IsLiteral:
    return T->isLiteralType();
  case UTT_IsEmpty:
    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
      return !RD->isUnion() && RD->isEmpty();
    return false;
  case UTT_IsPolymorphic:
    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
      return RD->isPolymorphic();
    return false;
  case UTT_IsAbstract:
    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
      return RD->isAbstract();
    return false;
  case UTT_IsFinal:
    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
      return RD->hasAttr<FinalAttr>();
    return false;
  case UTT_IsSigned:
    return T->isSignedIntegerType();
  case UTT_IsUnsigned:
    return T->isUnsignedIntegerType();

    // Type trait expressions which query classes regarding their construction,
    // destruction, and copying. Rather than being based directly on the
    // related type predicates in the standard, they are specified by both
    // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those
    // specifications.
    //
    //   1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
    //   2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
  case UTT_HasTrivialDefaultConstructor:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If __is_pod (type) is true then the trait is true, else if type is
    //   a cv class or union type (or array thereof) with a trivial default
    //   constructor ([class.ctor]) then the trait is true, else it is false.
    if (T.isPODType(Self.Context))
      return true;
    if (const RecordType *RT =
          C.getBaseElementType(T)->getAs<RecordType>())
      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
    return false;
  case UTT_HasTrivialCopy:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If __is_pod (type) is true or type is a reference type then
    //   the trait is true, else if type is a cv class or union type
    //   with a trivial copy constructor ([class.copy]) then the trait
    //   is true, else it is false.
    if (T.isPODType(Self.Context) || T->isReferenceType())
      return true;
    if (const RecordType *RT = T->getAs<RecordType>())
      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
    return false;
  case UTT_HasTrivialAssign:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If type is const qualified or is a reference type then the
    //   trait is false. Otherwise if __is_pod (type) is true then the
    //   trait is true, else if type is a cv class or union type with
    //   a trivial copy assignment ([class.copy]) then the trait is
    //   true, else it is false.
    // Note: the const and reference restrictions are interesting,
    // given that const and reference members don't prevent a class
    // from having a trivial copy assignment operator (but do cause
    // errors if the copy assignment operator is actually used, q.v.
    // [class.copy]p12).

    if (C.getBaseElementType(T).isConstQualified())
      return false;
    if (T.isPODType(Self.Context))
      return true;
    if (const RecordType *RT = T->getAs<RecordType>())
      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
    return false;
  case UTT_HasTrivialDestructor:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If __is_pod (type) is true or type is a reference type
    //   then the trait is true, else if type is a cv class or union
    //   type (or array thereof) with a trivial destructor
    //   ([class.dtor]) then the trait is true, else it is
    //   false.
    if (T.isPODType(Self.Context) || T->isReferenceType())
      return true;
      
    // Objective-C++ ARC: autorelease types don't require destruction.
    if (T->isObjCLifetimeType() && 
        T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
      return true;
      
    if (const RecordType *RT =
          C.getBaseElementType(T)->getAs<RecordType>())
      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
    return false;
  // TODO: Propagate nothrowness for implicitly declared special members.
  case UTT_HasNothrowAssign:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If type is const qualified or is a reference type then the
    //   trait is false. Otherwise if __has_trivial_assign (type)
    //   is true then the trait is true, else if type is a cv class
    //   or union type with copy assignment operators that are known
    //   not to throw an exception then the trait is true, else it is
    //   false.
    if (C.getBaseElementType(T).isConstQualified())
      return false;
    if (T->isReferenceType())
      return false;
    if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
      return true;     
    if (const RecordType *RT = T->getAs<RecordType>()) {
      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
      if (RD->hasTrivialCopyAssignment())
        return true;

      bool FoundAssign = false;
      DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
      LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
                       Sema::LookupOrdinaryName);
      if (Self.LookupQualifiedName(Res, RD)) {
        Res.suppressDiagnostics();
        for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
             Op != OpEnd; ++Op) {
          if (isa<FunctionTemplateDecl>(*Op))
            continue;
          
          CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
          if (Operator->isCopyAssignmentOperator()) {
            FoundAssign = true;
            const FunctionProtoType *CPT
                = Operator->getType()->getAs<FunctionProtoType>();
            if (CPT->getExceptionSpecType() == EST_Delayed)
              return false;
            if (!CPT->isNothrow(Self.Context))
              return false;
          }
        }
      }
      
      return FoundAssign;
    }
    return false;
  case UTT_HasNothrowCopy:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If __has_trivial_copy (type) is true then the trait is true, else
    //   if type is a cv class or union type with copy constructors that are
    //   known not to throw an exception then the trait is true, else it is
    //   false.
    if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType())
      return true;
    if (const RecordType *RT = T->getAs<RecordType>()) {
      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
      if (RD->hasTrivialCopyConstructor())
        return true;

      bool FoundConstructor = false;
      unsigned FoundTQs;
      DeclContext::lookup_const_iterator Con, ConEnd;
      for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
           Con != ConEnd; ++Con) {
        // A template constructor is never a copy constructor.
        // FIXME: However, it may actually be selected at the actual overload
        // resolution point.
        if (isa<FunctionTemplateDecl>(*Con))
          continue;
        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
        if (Constructor->isCopyConstructor(FoundTQs)) {
          FoundConstructor = true;
          const FunctionProtoType *CPT
              = Constructor->getType()->getAs<FunctionProtoType>();
          if (CPT->getExceptionSpecType() == EST_Delayed)
            return false;
          // FIXME: check whether evaluating default arguments can throw.
          // For now, we'll be conservative and assume that they can throw.
          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
            return false;
        }
      }

      return FoundConstructor;
    }
    return false;
  case UTT_HasNothrowConstructor:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If __has_trivial_constructor (type) is true then the trait is
    //   true, else if type is a cv class or union type (or array
    //   thereof) with a default constructor that is known not to
    //   throw an exception then the trait is true, else it is false.
    if (T.isPODType(C) || T->isObjCLifetimeType())
      return true;
    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
      if (RD->hasTrivialDefaultConstructor())
        return true;

      DeclContext::lookup_const_iterator Con, ConEnd;
      for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
           Con != ConEnd; ++Con) {
        // FIXME: In C++0x, a constructor template can be a default constructor.
        if (isa<FunctionTemplateDecl>(*Con))
          continue;
        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
        if (Constructor->isDefaultConstructor()) {
          const FunctionProtoType *CPT
              = Constructor->getType()->getAs<FunctionProtoType>();
          if (CPT->getExceptionSpecType() == EST_Delayed)
            return false;
          // TODO: check whether evaluating default arguments can throw.
          // For now, we'll be conservative and assume that they can throw.
          return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
        }
      }
    }
    return false;
  case UTT_HasVirtualDestructor:
    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
    //   If type is a class type with a virtual destructor ([class.dtor])
    //   then the trait is true, else it is false.
    if (const RecordType *Record = T->getAs<RecordType>()) {
      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
      if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD))
        return Destructor->isVirtual();
    }
    return false;

    // These type trait expressions are modeled on the specifications for the
    // Embarcadero C++0x type trait functions:
    //   http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
  case UTT_IsCompleteType:
    // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_):
    //   Returns True if and only if T is a complete type at the point of the
    //   function call.
    return !T->isIncompleteType();
  }
  llvm_unreachable("Type trait not covered by switch");
}

ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
                                     SourceLocation KWLoc,
                                     TypeSourceInfo *TSInfo,
                                     SourceLocation RParen) {
  QualType T = TSInfo->getType();
  if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
    return ExprError();

  bool Value = false;
  if (!T->isDependentType())
    Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T);

  return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
                                                RParen, Context.BoolTy));
}

ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
                                      SourceLocation KWLoc,
                                      ParsedType LhsTy,
                                      ParsedType RhsTy,
                                      SourceLocation RParen) {
  TypeSourceInfo *LhsTSInfo;
  QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
  if (!LhsTSInfo)
    LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);

  TypeSourceInfo *RhsTSInfo;
  QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
  if (!RhsTSInfo)
    RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);

  return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
}

static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
                                    QualType LhsT, QualType RhsT,
                                    SourceLocation KeyLoc) {
  assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
         "Cannot evaluate traits of dependent types");

  switch(BTT) {
  case BTT_IsBaseOf: {
    // C++0x [meta.rel]p2
    // Base is a base class of Derived without regard to cv-qualifiers or
    // Base and Derived are not unions and name the same class type without
    // regard to cv-qualifiers.

    const RecordType *lhsRecord = LhsT->getAs<RecordType>();
    if (!lhsRecord) return false;

    const RecordType *rhsRecord = RhsT->getAs<RecordType>();
    if (!rhsRecord) return false;

    assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
             == (lhsRecord == rhsRecord));

    if (lhsRecord == rhsRecord)
      return !lhsRecord->getDecl()->isUnion();

    // C++0x [meta.rel]p2:
    //   If Base and Derived are class types and are different types
    //   (ignoring possible cv-qualifiers) then Derived shall be a
    //   complete type.
    if (Self.RequireCompleteType(KeyLoc, RhsT, 
                          diag::err_incomplete_type_used_in_type_trait_expr))
      return false;

    return cast<CXXRecordDecl>(rhsRecord->getDecl())
      ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
  }
  case BTT_IsSame:
    return Self.Context.hasSameType(LhsT, RhsT);
  case BTT_TypeCompatible:
    return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
                                           RhsT.getUnqualifiedType());
  case BTT_IsConvertible:
  case BTT_IsConvertibleTo: {
    // C++0x [meta.rel]p4:
    //   Given the following function prototype:
    //
    //     template <class T> 
    //       typename add_rvalue_reference<T>::type create();
    //
    //   the predicate condition for a template specialization 
    //   is_convertible<From, To> shall be satisfied if and only if 
    //   the return expression in the following code would be 
    //   well-formed, including any implicit conversions to the return
    //   type of the function:
    //
    //     To test() { 
    //       return create<From>();
    //     }
    //
    //   Access checking is performed as if in a context unrelated to To and 
    //   From. Only the validity of the immediate context of the expression 
    //   of the return-statement (including conversions to the return type)
    //   is considered.
    //
    // We model the initialization as a copy-initialization of a temporary
    // of the appropriate type, which for this expression is identical to the
    // return statement (since NRVO doesn't apply).
    if (LhsT->isObjectType() || LhsT->isFunctionType())
      LhsT = Self.Context.getRValueReferenceType(LhsT);
    
    InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
    OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
                         Expr::getValueKindForType(LhsT));
    Expr *FromPtr = &From;
    InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, 
                                                           SourceLocation()));
    
    // Perform the initialization within a SFINAE trap at translation unit 
    // scope.
    Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
    Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
    InitializationSequence Init(Self, To, Kind, &FromPtr, 1);
    if (Init.Failed())
      return false;

    ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1));
    return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
  }
  }
  llvm_unreachable("Unknown type trait or not implemented");
}

ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
                                      SourceLocation KWLoc,
                                      TypeSourceInfo *LhsTSInfo,
                                      TypeSourceInfo *RhsTSInfo,
                                      SourceLocation RParen) {
  QualType LhsT = LhsTSInfo->getType();
  QualType RhsT = RhsTSInfo->getType();

  if (BTT == BTT_TypeCompatible) {
    if (getLangOptions().CPlusPlus) {
      Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
        << SourceRange(KWLoc, RParen);
      return ExprError();
    }
  }

  bool Value = false;
  if (!LhsT->isDependentType() && !RhsT->isDependentType())
    Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);

  // Select trait result type.
  QualType ResultType;
  switch (BTT) {
  case BTT_IsBaseOf:       ResultType = Context.BoolTy; break;
  case BTT_IsConvertible:  ResultType = Context.BoolTy; break;
  case BTT_IsSame:         ResultType = Context.BoolTy; break;
  case BTT_TypeCompatible: ResultType = Context.IntTy; break;
  case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
  }

  return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
                                                 RhsTSInfo, Value, RParen,
                                                 ResultType));
}

ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
                                     SourceLocation KWLoc,
                                     ParsedType Ty,
                                     Expr* DimExpr,
                                     SourceLocation RParen) {
  TypeSourceInfo *TSInfo;
  QualType T = GetTypeFromParser(Ty, &TSInfo);
  if (!TSInfo)
    TSInfo = Context.getTrivialTypeSourceInfo(T);

  return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen);
}

static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
                                           QualType T, Expr *DimExpr,
                                           SourceLocation KeyLoc) {
  assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");

  switch(ATT) {
  case ATT_ArrayRank:
    if (T->isArrayType()) {
      unsigned Dim = 0;
      while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
        ++Dim;
        T = AT->getElementType();
      }
      return Dim;
    }
    return 0;

  case ATT_ArrayExtent: {
    llvm::APSInt Value;
    uint64_t Dim;
    if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) {
      if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) {
        Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
          DimExpr->getSourceRange();
        return false;
      }
      Dim = Value.getLimitedValue();
    } else {
      Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) <<
        DimExpr->getSourceRange();
      return false;
    }

    if (T->isArrayType()) {
      unsigned D = 0;
      bool Matched = false;
      while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
        if (Dim == D) {
          Matched = true;
          break;
        }
        ++D;
        T = AT->getElementType();
      }

      if (Matched && T->isArrayType()) {
        if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T))
          return CAT->getSize().getLimitedValue();
      }
    }
    return 0;
  }
  }
  llvm_unreachable("Unknown type trait or not implemented");
}

ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT,
                                     SourceLocation KWLoc,
                                     TypeSourceInfo *TSInfo,
                                     Expr* DimExpr,
                                     SourceLocation RParen) {
  QualType T = TSInfo->getType();

  // FIXME: This should likely be tracked as an APInt to remove any host
  // assumptions about the width of size_t on the target.
  uint64_t Value = 0;
  if (!T->isDependentType())
    Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc);

  // While the specification for these traits from the Embarcadero C++
  // compiler's documentation says the return type is 'unsigned int', Clang
  // returns 'size_t'. On Windows, the primary platform for the Embarcadero
  // compiler, there is no difference. On several other platforms this is an
  // important distinction.
  return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value,
                                                DimExpr, RParen,
                                                Context.getSizeType()));
}

ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET,
                                      SourceLocation KWLoc,
                                      Expr *Queried,
                                      SourceLocation RParen) {
  // If error parsing the expression, ignore.
  if (!Queried)
    return ExprError();

  ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen);

  return move(Result);
}

static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {
  switch (ET) {
  case ET_IsLValueExpr: return E->isLValue();
  case ET_IsRValueExpr: return E->isRValue();
  }
  llvm_unreachable("Expression trait not covered by switch");
}

ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET,
                                      SourceLocation KWLoc,
                                      Expr *Queried,
                                      SourceLocation RParen) {
  if (Queried->isTypeDependent()) {
    // Delay type-checking for type-dependent expressions.
  } else if (Queried->getType()->isPlaceholderType()) {
    ExprResult PE = CheckPlaceholderExpr(Queried);
    if (PE.isInvalid()) return ExprError();
    return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen);
  }

  bool Value = EvaluateExpressionTrait(ET, Queried);

  return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value,
                                                 RParen, Context.BoolTy));
}

QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
                                            ExprValueKind &VK,
                                            SourceLocation Loc,
                                            bool isIndirect) {
  assert(!LHS.get()->getType()->isPlaceholderType() &&
         !RHS.get()->getType()->isPlaceholderType() &&
         "placeholders should have been weeded out by now");

  // The LHS undergoes lvalue conversions if this is ->*.
  if (isIndirect) {
    LHS = DefaultLvalueConversion(LHS.take());
    if (LHS.isInvalid()) return QualType();
  }

  // The RHS always undergoes lvalue conversions.
  RHS = DefaultLvalueConversion(RHS.take());
  if (RHS.isInvalid()) return QualType();

  const char *OpSpelling = isIndirect ? "->*" : ".*";
  // C++ 5.5p2
  //   The binary operator .* [p3: ->*] binds its second operand, which shall
  //   be of type "pointer to member of T" (where T is a completely-defined
  //   class type) [...]
  QualType RHSType = RHS.get()->getType();
  const MemberPointerType *MemPtr = RHSType->getAs<MemberPointerType>();
  if (!MemPtr) {
    Diag(Loc, diag::err_bad_memptr_rhs)
      << OpSpelling << RHSType << RHS.get()->getSourceRange();
    return QualType();
  }

  QualType Class(MemPtr->getClass(), 0);

  // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the
  // member pointer points must be completely-defined. However, there is no
  // reason for this semantic distinction, and the rule is not enforced by
  // other compilers. Therefore, we do not check this property, as it is
  // likely to be considered a defect.

  // C++ 5.5p2
  //   [...] to its first operand, which shall be of class T or of a class of
  //   which T is an unambiguous and accessible base class. [p3: a pointer to
  //   such a class]
  QualType LHSType = LHS.get()->getType();
  if (isIndirect) {
    if (const PointerType *Ptr = LHSType->getAs<PointerType>())
      LHSType = Ptr->getPointeeType();
    else {
      Diag(Loc, diag::err_bad_memptr_lhs)
        << OpSpelling << 1 << LHSType
        << FixItHint::CreateReplacement(SourceRange(Loc), ".*");
      return QualType();
    }
  }

  if (!Context.hasSameUnqualifiedType(Class, LHSType)) {
    // If we want to check the hierarchy, we need a complete type.
    if (RequireCompleteType(Loc, LHSType, PDiag(diag::err_bad_memptr_lhs)
        << OpSpelling << (int)isIndirect)) {
      return QualType();
    }
    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);
    // FIXME: Would it be useful to print full ambiguity paths, or is that
    // overkill?
    if (!IsDerivedFrom(LHSType, Class, Paths) ||
        Paths.isAmbiguous(Context.getCanonicalType(Class))) {
      Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
        << (int)isIndirect << LHS.get()->getType();
      return QualType();
    }
    // Cast LHS to type of use.
    QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
    ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();

    CXXCastPath BasePath;
    BuildBasePathArray(Paths, BasePath);
    LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
                            &BasePath);
  }

  if (isa<CXXScalarValueInitExpr>(RHS.get()->IgnoreParens())) {
    // Diagnose use of pointer-to-member type which when used as
    // the functional cast in a pointer-to-member expression.
    Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
     return QualType();
  }

  // C++ 5.5p2
  //   The result is an object or a function of the type specified by the
  //   second operand.
  // The cv qualifiers are the union of those in the pointer and the left side,
  // in accordance with 5.5p5 and 5.2.5.
  QualType Result = MemPtr->getPointeeType();
  Result = Context.getCVRQualifiedType(Result, LHSType.getCVRQualifiers());

  // C++0x [expr.mptr.oper]p6:
  //   In a .* expression whose object expression is an rvalue, the program is
  //   ill-formed if the second operand is a pointer to member function with
  //   ref-qualifier &. In a ->* expression or in a .* expression whose object
  //   expression is an lvalue, the program is ill-formed if the second operand
  //   is a pointer to member function with ref-qualifier &&.
  if (const FunctionProtoType *Proto = Result->getAs<FunctionProtoType>()) {
    switch (Proto->getRefQualifier()) {
    case RQ_None:
      // Do nothing
      break;

    case RQ_LValue:
      if (!isIndirect && !LHS.get()->Classify(Context).isLValue())
        Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
          << RHSType << 1 << LHS.get()->getSourceRange();
      break;

    case RQ_RValue:
      if (isIndirect || !LHS.get()->Classify(Context).isRValue())
        Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
          << RHSType << 0 << LHS.get()->getSourceRange();
      break;
    }
  }

  // C++ [expr.mptr.oper]p6:
  //   The result of a .* expression whose second operand is a pointer
  //   to a data member is of the same value category as its
  //   first operand. The result of a .* expression whose second
  //   operand is a pointer to a member function is a prvalue. The
  //   result of an ->* expression is an lvalue if its second operand
  //   is a pointer to data member and a prvalue otherwise.
  if (Result->isFunctionType()) {
    VK = VK_RValue;
    return Context.BoundMemberTy;
  } else if (isIndirect) {
    VK = VK_LValue;
  } else {
    VK = LHS.get()->getValueKind();
  }

  return Result;
}

/// \brief Try to convert a type to another according to C++0x 5.16p3.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, the two operands are attempted to be
/// converted to each other. This function does the conversion in one direction.
/// It returns true if the program is ill-formed and has already been diagnosed
/// as such.
static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
                                SourceLocation QuestionLoc,
                                bool &HaveConversion,
                                QualType &ToType) {
  HaveConversion = false;
  ToType = To->getType();

  InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(),
                                                           SourceLocation());
  // C++0x 5.16p3
  //   The process for determining whether an operand expression E1 of type T1
  //   can be converted to match an operand expression E2 of type T2 is defined
  //   as follows:
  //   -- If E2 is an lvalue:
  bool ToIsLvalue = To->isLValue();
  if (ToIsLvalue) {
    //   E1 can be converted to match E2 if E1 can be implicitly converted to
    //   type "lvalue reference to T2", subject to the constraint that in the
    //   conversion the reference must bind directly to E1.
    QualType T = Self.Context.getLValueReferenceType(ToType);
    InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);

    InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
    if (InitSeq.isDirectReferenceBinding()) {
      ToType = T;
      HaveConversion = true;
      return false;
    }

    if (InitSeq.isAmbiguous())
      return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
  }

  //   -- If E2 is an rvalue, or if the conversion above cannot be done:
  //      -- if E1 and E2 have class type, and the underlying class types are
  //         the same or one is a base class of the other:
  QualType FTy = From->getType();
  QualType TTy = To->getType();
  const RecordType *FRec = FTy->getAs<RecordType>();
  const RecordType *TRec = TTy->getAs<RecordType>();
  bool FDerivedFromT = FRec && TRec && FRec != TRec &&
                       Self.IsDerivedFrom(FTy, TTy);
  if (FRec && TRec &&
      (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
    //         E1 can be converted to match E2 if the class of T2 is the
    //         same type as, or a base class of, the class of T1, and
    //         [cv2 > cv1].
    if (FRec == TRec || FDerivedFromT) {
      if (TTy.isAtLeastAsQualifiedAs(FTy)) {
        InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
        InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
        if (InitSeq) {
          HaveConversion = true;
          return false;
        }

        if (InitSeq.isAmbiguous())
          return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
      }
    }

    return false;
  }

  //     -- Otherwise: E1 can be converted to match E2 if E1 can be
  //        implicitly converted to the type that expression E2 would have
  //        if E2 were converted to an rvalue (or the type it has, if E2 is
  //        an rvalue).
  //
  // This actually refers very narrowly to the lvalue-to-rvalue conversion, not
  // to the array-to-pointer or function-to-pointer conversions.
  if (!TTy->getAs<TagType>())
    TTy = TTy.getUnqualifiedType();

  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
  InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
  HaveConversion = !InitSeq.Failed();
  ToType = TTy;
  if (InitSeq.isAmbiguous())
    return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);

  return false;
}

/// \brief Try to find a common type for two according to C++0x 5.16p5.
///
/// This is part of the parameter validation for the ? operator. If either
/// value operand is a class type, overload resolution is used to find a
/// conversion to a common type.
static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS,
                                    SourceLocation QuestionLoc) {
  Expr *Args[2] = { LHS.get(), RHS.get() };
  OverloadCandidateSet CandidateSet(QuestionLoc);
  Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2,
                                    CandidateSet);

  OverloadCandidateSet::iterator Best;
  switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) {
    case OR_Success: {
      // We found a match. Perform the conversions on the arguments and move on.
      ExprResult LHSRes =
        Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0],
                                       Best->Conversions[0], Sema::AA_Converting);
      if (LHSRes.isInvalid())
        break;
      LHS = move(LHSRes);

      ExprResult RHSRes =
        Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1],
                                       Best->Conversions[1], Sema::AA_Converting);
      if (RHSRes.isInvalid())
        break;
      RHS = move(RHSRes);
      if (Best->Function)
        Self.MarkDeclarationReferenced(QuestionLoc, Best->Function);
      return false;
    }
    
    case OR_No_Viable_Function:

      // Emit a better diagnostic if one of the expressions is a null pointer
      // constant and the other is a pointer type. In this case, the user most
      // likely forgot to take the address of the other expression.
      if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
        return true;

      Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
        << LHS.get()->getType() << RHS.get()->getType()
        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
      return true;

    case OR_Ambiguous:
      Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl)
        << LHS.get()->getType() << RHS.get()->getType()
        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
      // FIXME: Print the possible common types by printing the return types of
      // the viable candidates.
      break;

    case OR_Deleted:
      llvm_unreachable("Conditional operator has only built-in overloads");
  }
  return true;
}

/// \brief Perform an "extended" implicit conversion as returned by
/// TryClassUnification.
static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
  InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
  InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(),
                                                           SourceLocation());
  Expr *Arg = E.take();
  InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1);
  ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1));
  if (Result.isInvalid())
    return true;

  E = Result;
  return false;
}

/// \brief Check the operands of ?: under C++ semantics.
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
                                           ExprValueKind &VK, ExprObjectKind &OK,
                                           SourceLocation QuestionLoc) {
  // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
  // interface pointers.

  // C++0x 5.16p1
  //   The first expression is contextually converted to bool.
  if (!Cond.get()->isTypeDependent()) {
    ExprResult CondRes = CheckCXXBooleanCondition(Cond.take());
    if (CondRes.isInvalid())
      return QualType();
    Cond = move(CondRes);
  }

  // Assume r-value.
  VK = VK_RValue;
  OK = OK_Ordinary;

  // Either of the arguments dependent?
  if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent())
    return Context.DependentTy;

  // C++0x 5.16p2
  //   If either the second or the third operand has type (cv) void, ...
  QualType LTy = LHS.get()->getType();
  QualType RTy = RHS.get()->getType();
  bool LVoid = LTy->isVoidType();
  bool RVoid = RTy->isVoidType();
  if (LVoid || RVoid) {
    //   ... then the [l2r] conversions are performed on the second and third
    //   operands ...
    LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
    RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
    if (LHS.isInvalid() || RHS.isInvalid())
      return QualType();
    LTy = LHS.get()->getType();
    RTy = RHS.get()->getType();

    //   ... and one of the following shall hold:
    //   -- The second or the third operand (but not both) is a throw-
    //      expression; the result is of the type of the other and is an rvalue.
    bool LThrow = isa<CXXThrowExpr>(LHS.get());
    bool RThrow = isa<CXXThrowExpr>(RHS.get());
    if (LThrow && !RThrow)
      return RTy;
    if (RThrow && !LThrow)
      return LTy;

    //   -- Both the second and third operands have type void; the result is of
    //      type void and is an rvalue.
    if (LVoid && RVoid)
      return Context.VoidTy;

    // Neither holds, error.
    Diag(QuestionLoc, diag::err_conditional_void_nonvoid)
      << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1)
      << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
    return QualType();
  }

  // Neither is void.

  // C++0x 5.16p3
  //   Otherwise, if the second and third operand have different types, and
  //   either has (cv) class type, and attempt is made to convert each of those
  //   operands to the other.
  if (!Context.hasSameType(LTy, RTy) &&
      (LTy->isRecordType() || RTy->isRecordType())) {
    ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
    // These return true if a single direction is already ambiguous.
    QualType L2RType, R2LType;
    bool HaveL2R, HaveR2L;
    if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType))
      return QualType();
    if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType))
      return QualType();

    //   If both can be converted, [...] the program is ill-formed.
    if (HaveL2R && HaveR2L) {
      Diag(QuestionLoc, diag::err_conditional_ambiguous)
        << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
      return QualType();
    }

    //   If exactly one conversion is possible, that conversion is applied to
    //   the chosen operand and the converted operands are used in place of the
    //   original operands for the remainder of this section.
    if (HaveL2R) {
      if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid())
        return QualType();
      LTy = LHS.get()->getType();
    } else if (HaveR2L) {
      if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid())
        return QualType();
      RTy = RHS.get()->getType();
    }
  }

  // C++0x 5.16p4
  //   If the second and third operands are glvalues of the same value
  //   category and have the same type, the result is of that type and
  //   value category and it is a bit-field if the second or the third
  //   operand is a bit-field, or if both are bit-fields.
  // We only extend this to bitfields, not to the crazy other kinds of
  // l-values.
  bool Same = Context.hasSameType(LTy, RTy);
  if (Same &&
      LHS.get()->isGLValue() &&
      LHS.get()->getValueKind() == RHS.get()->getValueKind() &&
      LHS.get()->isOrdinaryOrBitFieldObject() &&
      RHS.get()->isOrdinaryOrBitFieldObject()) {
    VK = LHS.get()->getValueKind();
    if (LHS.get()->getObjectKind() == OK_BitField ||
        RHS.get()->getObjectKind() == OK_BitField)
      OK = OK_BitField;
    return LTy;
  }

  // C++0x 5.16p5
  //   Otherwise, the result is an rvalue. If the second and third operands
  //   do not have the same type, and either has (cv) class type, ...
  if (!Same && (LTy->isRecordType() || RTy->isRecordType())) {
    //   ... overload resolution is used to determine the conversions (if any)
    //   to be applied to the operands. If the overload resolution fails, the
    //   program is ill-formed.
    if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc))
      return QualType();
  }

  // C++0x 5.16p6
  //   LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
  //   conversions are performed on the second and third operands.
  LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
  RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
  if (LHS.isInvalid() || RHS.isInvalid())
    return QualType();
  LTy = LHS.get()->getType();
  RTy = RHS.get()->getType();

  //   After those conversions, one of the following shall hold:
  //   -- The second and third operands have the same type; the result
  //      is of that type. If the operands have class type, the result
  //      is a prvalue temporary of the result type, which is
  //      copy-initialized from either the second operand or the third
  //      operand depending on the value of the first operand.
  if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
    if (LTy->isRecordType()) {
      // The operands have class type. Make a temporary copy.
      InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
      ExprResult LHSCopy = PerformCopyInitialization(Entity,
                                                     SourceLocation(),
                                                     LHS);
      if (LHSCopy.isInvalid())
        return QualType();

      ExprResult RHSCopy = PerformCopyInitialization(Entity,
                                                     SourceLocation(),
                                                     RHS);
      if (RHSCopy.isInvalid())
        return QualType();

      LHS = LHSCopy;
      RHS = RHSCopy;
    }

    return LTy;
  }

  // Extension: conditional operator involving vector types.
  if (LTy->isVectorType() || RTy->isVectorType())
    return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);

  //   -- The second and third operands have arithmetic or enumeration type;
  //      the usual arithmetic conversions are performed to bring them to a
  //      common type, and the result is of that type.
  if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
    UsualArithmeticConversions(LHS, RHS);
    if (LHS.isInvalid() || RHS.isInvalid())
      return QualType();
    return LHS.get()->getType();
  }

  //   -- The second and third operands have pointer type, or one has pointer
  //      type and the other is a null pointer constant; pointer conversions
  //      and qualification conversions are performed to bring them to their
  //      composite pointer type. The result is of the composite pointer type.
  //   -- The second and third operands have pointer to member type, or one has
  //      pointer to member type and the other is a null pointer constant;
  //      pointer to member conversions and qualification conversions are
  //      performed to bring them to a common type, whose cv-qualification
  //      shall match the cv-qualification of either the second or the third
  //      operand. The result is of the common type.
  bool NonStandardCompositeType = false;
  QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
                              isSFINAEContext()? 0 : &NonStandardCompositeType);
  if (!Composite.isNull()) {
    if (NonStandardCompositeType)
      Diag(QuestionLoc,
           diag::ext_typecheck_cond_incompatible_operands_nonstandard)
        << LTy << RTy << Composite
        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();

    return Composite;
  }

  // Similarly, attempt to find composite type of two objective-c pointers.
  Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
  if (!Composite.isNull())
    return Composite;

  // Check if we are using a null with a non-pointer type.
  if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
    return QualType();

  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
    << LHS.get()->getType() << RHS.get()->getType()
    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
  return QualType();
}

/// \brief Find a merged pointer type and convert the two expressions to it.
///
/// This finds the composite pointer type (or member pointer type) for @p E1
/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this
/// type and returns it.
/// It does not emit diagnostics.
///
/// \param Loc The location of the operator requiring these two expressions to
/// be converted to the composite pointer type.
///
/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find
/// a non-standard (but still sane) composite type to which both expressions
/// can be converted. When such a type is chosen, \c *NonStandardCompositeType
/// will be set true.
QualType Sema::FindCompositePointerType(SourceLocation Loc,
                                        Expr *&E1, Expr *&E2,
                                        bool *NonStandardCompositeType) {
  if (NonStandardCompositeType)
    *NonStandardCompositeType = false;

  assert(getLangOptions().CPlusPlus && "This function assumes C++");
  QualType T1 = E1->getType(), T2 = E2->getType();

  if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
      !T2->isAnyPointerType() && !T2->isMemberPointerType())
   return QualType();

  // C++0x 5.9p2
  //   Pointer conversions and qualification conversions are performed on
  //   pointer operands to bring them to their composite pointer type. If
  //   one operand is a null pointer constant, the composite pointer type is
  //   the type of the other operand.
  if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
    if (T2->isMemberPointerType())
      E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take();
    else
      E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
    return T2;
  }
  if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
    if (T1->isMemberPointerType())
      E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take();
    else
      E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
    return T1;
  }

  // Now both have to be pointers or member pointers.
  if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
      (!T2->isPointerType() && !T2->isMemberPointerType()))
    return QualType();

  //   Otherwise, of one of the operands has type "pointer to cv1 void," then
  //   the other has type "pointer to cv2 T" and the composite pointer type is
  //   "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
  //   Otherwise, the composite pointer type is a pointer type similar to the
  //   type of one of the operands, with a cv-qualification signature that is
  //   the union of the cv-qualification signatures of the operand types.
  // In practice, the first part here is redundant; it's subsumed by the second.
  // What we do here is, we build the two possible composite types, and try the
  // conversions in both directions. If only one works, or if the two composite
  // types are the same, we have succeeded.
  // FIXME: extended qualifiers?
  typedef SmallVector<unsigned, 4> QualifierVector;
  QualifierVector QualifierUnion;
  typedef SmallVector<std::pair<const Type *, const Type *>, 4>
      ContainingClassVector;
  ContainingClassVector MemberOfClass;
  QualType Composite1 = Context.getCanonicalType(T1),
           Composite2 = Context.getCanonicalType(T2);
  unsigned NeedConstBefore = 0;
  do {
    const PointerType *Ptr1, *Ptr2;
    if ((Ptr1 = Composite1->getAs<PointerType>()) &&
        (Ptr2 = Composite2->getAs<PointerType>())) {
      Composite1 = Ptr1->getPointeeType();
      Composite2 = Ptr2->getPointeeType();

      // If we're allowed to create a non-standard composite type, keep track
      // of where we need to fill in additional 'const' qualifiers.
      if (NonStandardCompositeType &&
          Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
        NeedConstBefore = QualifierUnion.size();

      QualifierUnion.push_back(
                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
      MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
      continue;
    }

    const MemberPointerType *MemPtr1, *MemPtr2;
    if ((MemPtr1 = Composite1->getAs<MemberPointerType>()) &&
        (MemPtr2 = Composite2->getAs<MemberPointerType>())) {
      Composite1 = MemPtr1->getPointeeType();
      Composite2 = MemPtr2->getPointeeType();

      // If we're allowed to create a non-standard composite type, keep track
      // of where we need to fill in additional 'const' qualifiers.
      if (NonStandardCompositeType &&
          Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
        NeedConstBefore = QualifierUnion.size();

      QualifierUnion.push_back(
                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
      MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(),
                                             MemPtr2->getClass()));
      continue;
    }

    // FIXME: block pointer types?

    // Cannot unwrap any more types.
    break;
  } while (true);

  if (NeedConstBefore && NonStandardCompositeType) {
    // Extension: Add 'const' to qualifiers that come before the first qualifier
    // mismatch, so that our (non-standard!) composite type meets the
    // requirements of C++ [conv.qual]p4 bullet 3.
    for (unsigned I = 0; I != NeedConstBefore; ++I) {
      if ((QualifierUnion[I] & Qualifiers::Const) == 0) {
        QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const;
        *NonStandardCompositeType = true;
      }
    }
  }

  // Rewrap the composites as pointers or member pointers with the union CVRs.
  ContainingClassVector::reverse_iterator MOC
    = MemberOfClass.rbegin();
  for (QualifierVector::reverse_iterator
         I = QualifierUnion.rbegin(),
         E = QualifierUnion.rend();
       I != E; (void)++I, ++MOC) {
    Qualifiers Quals = Qualifiers::fromCVRMask(*I);
    if (MOC->first && MOC->second) {
      // Rebuild member pointer type
      Composite1 = Context.getMemberPointerType(
                                    Context.getQualifiedType(Composite1, Quals),
                                    MOC->first);
      Composite2 = Context.getMemberPointerType(
                                    Context.getQualifiedType(Composite2, Quals),
                                    MOC->second);
    } else {
      // Rebuild pointer type
      Composite1
        = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
      Composite2
        = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
    }
  }

  // Try to convert to the first composite pointer type.
  InitializedEntity Entity1
    = InitializedEntity::InitializeTemporary(Composite1);
  InitializationKind Kind
    = InitializationKind::CreateCopy(Loc, SourceLocation());
  InitializationSequence E1ToC1(*this, Entity1, Kind, &E1, 1);
  InitializationSequence E2ToC1(*this, Entity1, Kind, &E2, 1);

  if (E1ToC1 && E2ToC1) {
    // Conversion to Composite1 is viable.
    if (!Context.hasSameType(Composite1, Composite2)) {
      // Composite2 is a different type from Composite1. Check whether
      // Composite2 is also viable.
      InitializedEntity Entity2
        = InitializedEntity::InitializeTemporary(Composite2);
      InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
      InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
      if (E1ToC2 && E2ToC2) {
        // Both Composite1 and Composite2 are viable and are different;
        // this is an ambiguity.
        return QualType();
      }
    }

    // Convert E1 to Composite1
    ExprResult E1Result
      = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1));
    if (E1Result.isInvalid())
      return QualType();
    E1 = E1Result.takeAs<Expr>();

    // Convert E2 to Composite1
    ExprResult E2Result
      = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1));
    if (E2Result.isInvalid())
      return QualType();
    E2 = E2Result.takeAs<Expr>();

    return Composite1;
  }

  // Check whether Composite2 is viable.
  InitializedEntity Entity2
    = InitializedEntity::InitializeTemporary(Composite2);
  InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
  InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
  if (!E1ToC2 || !E2ToC2)
    return QualType();

  // Convert E1 to Composite2
  ExprResult E1Result
    = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1));
  if (E1Result.isInvalid())
    return QualType();
  E1 = E1Result.takeAs<Expr>();

  // Convert E2 to Composite2
  ExprResult E2Result
    = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1));
  if (E2Result.isInvalid())
    return QualType();
  E2 = E2Result.takeAs<Expr>();

  return Composite2;
}

ExprResult Sema::MaybeBindToTemporary(Expr *E) {
  if (!E)
    return ExprError();

  assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");

  // If the result is a glvalue, we shouldn't bind it.
  if (!E->isRValue())
    return Owned(E);

  // In ARC, calls that return a retainable type can return retained,
  // in which case we have to insert a consuming cast.
  if (getLangOptions().ObjCAutoRefCount &&
      E->getType()->isObjCRetainableType()) {

    bool ReturnsRetained;

    // For actual calls, we compute this by examining the type of the
    // called value.
    if (CallExpr *Call = dyn_cast<CallExpr>(E)) {
      Expr *Callee = Call->getCallee()->IgnoreParens();
      QualType T = Callee->getType();

      if (T == Context.BoundMemberTy) {
        // Handle pointer-to-members.
        if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Callee))
          T = BinOp->getRHS()->getType();
        else if (MemberExpr *Mem = dyn_cast<MemberExpr>(Callee))
          T = Mem->getMemberDecl()->getType();
      }
      
      if (const PointerType *Ptr = T->getAs<PointerType>())
        T = Ptr->getPointeeType();
      else if (const BlockPointerType *Ptr = T->getAs<BlockPointerType>())
        T = Ptr->getPointeeType();
      else if (const MemberPointerType *MemPtr = T->getAs<MemberPointerType>())
        T = MemPtr->getPointeeType();
      
      const FunctionType *FTy = T->getAs<FunctionType>();
      assert(FTy && "call to value not of function type?");
      ReturnsRetained = FTy->getExtInfo().getProducesResult();

    // ActOnStmtExpr arranges things so that StmtExprs of retainable
    // type always produce a +1 object.
    } else if (isa<StmtExpr>(E)) {
      ReturnsRetained = true;

    // For message sends and property references, we try to find an
    // actual method.  FIXME: we should infer retention by selector in
    // cases where we don't have an actual method.
    } else {
      ObjCMethodDecl *D = 0;
      if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
        D = Send->getMethodDecl();
      }

      ReturnsRetained = (D && D->hasAttr<NSReturnsRetainedAttr>());

      // Don't do reclaims on performSelector calls; despite their
      // return type, the invoked method doesn't necessarily actually
      // return an object.
      if (!ReturnsRetained &&
          D && D->getMethodFamily() == OMF_performSelector)
        return Owned(E);
    }

    // Don't reclaim an object of Class type.
    if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType())
      return Owned(E);

    ExprNeedsCleanups = true;

    CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
                                   : CK_ARCReclaimReturnedObject);
    return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0,
                                          VK_RValue));
  }

  if (!getLangOptions().CPlusPlus)
    return Owned(E);

  QualType ET = Context.getBaseElementType(E->getType());
  const RecordType *RT = ET->getAs<RecordType>();
  if (!RT)
    return Owned(E);

  // That should be enough to guarantee that this type is complete.
  // If it has a trivial destructor, we can avoid the extra copy.
  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
  if (RD->isInvalidDecl() || RD->hasTrivialDestructor())
    return Owned(E);

  CXXDestructorDecl *Destructor = LookupDestructor(RD);

  CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor);
  if (Destructor) {
    MarkDeclarationReferenced(E->getExprLoc(), Destructor);
    CheckDestructorAccess(E->getExprLoc(), Destructor,
                          PDiag(diag::err_access_dtor_temp)
                            << E->getType());

    // We need a cleanup, but we don't need to remember the temporary.
    ExprNeedsCleanups = true;
  }
  return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
}

ExprResult
Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
  if (SubExpr.isInvalid())
    return ExprError();

  return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
}

Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
  assert(SubExpr && "sub expression can't be null!");

  unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects;
  assert(ExprCleanupObjects.size() >= FirstCleanup);
  assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup);
  if (!ExprNeedsCleanups)
    return SubExpr;

  ArrayRef<ExprWithCleanups::CleanupObject> Cleanups
    = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup,
                         ExprCleanupObjects.size() - FirstCleanup);

  Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups);
  DiscardCleanupsInEvaluationContext();

  return E;
}

Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
  assert(SubStmt && "sub statement can't be null!");

  if (!ExprNeedsCleanups)
    return SubStmt;

  // FIXME: In order to attach the temporaries, wrap the statement into
  // a StmtExpr; currently this is only used for asm statements.
  // This is hacky, either create a new CXXStmtWithTemporaries statement or
  // a new AsmStmtWithTemporaries.
  CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1,
                                                      SourceLocation(),
                                                      SourceLocation());
  Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
                                   SourceLocation());
  return MaybeCreateExprWithCleanups(E);
}

ExprResult
Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
                                   tok::TokenKind OpKind, ParsedType &ObjectType,
                                   bool &MayBePseudoDestructor) {
  // Since this might be a postfix expression, get rid of ParenListExprs.
  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
  if (Result.isInvalid()) return ExprError();
  Base = Result.get();

  Result = CheckPlaceholderExpr(Base);
  if (Result.isInvalid()) return ExprError();
  Base = Result.take();

  QualType BaseType = Base->getType();
  MayBePseudoDestructor = false;
  if (BaseType->isDependentType()) {
    // If we have a pointer to a dependent type and are using the -> operator,
    // the object type is the type that the pointer points to. We might still
    // have enough information about that type to do something useful.
    if (OpKind == tok::arrow)
      if (const PointerType *Ptr = BaseType->getAs<PointerType>())
        BaseType = Ptr->getPointeeType();

    ObjectType = ParsedType::make(BaseType);
    MayBePseudoDestructor = true;
    return Owned(Base);
  }

  // C++ [over.match.oper]p8:
  //   [...] When operator->returns, the operator-> is applied  to the value
  //   returned, with the original second operand.
  if (OpKind == tok::arrow) {
    // The set of types we've considered so far.
    llvm::SmallPtrSet<CanQualType,8> CTypes;
    SmallVector<SourceLocation, 8> Locations;
    CTypes.insert(Context.getCanonicalType(BaseType));

    while (BaseType->isRecordType()) {
      Result = BuildOverloadedArrowExpr(S, Base, OpLoc);
      if (Result.isInvalid())
        return ExprError();
      Base = Result.get();
      if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
        Locations.push_back(OpCall->getDirectCallee()->getLocation());
      BaseType = Base->getType();
      CanQualType CBaseType = Context.getCanonicalType(BaseType);
      if (!CTypes.insert(CBaseType)) {
        Diag(OpLoc, diag::err_operator_arrow_circular);
        for (unsigned i = 0; i < Locations.size(); i++)
          Diag(Locations[i], diag::note_declared_at);
        return ExprError();
      }
    }

    if (BaseType->isPointerType())
      BaseType = BaseType->getPointeeType();
  }

  // We could end up with various non-record types here, such as extended
  // vector types or Objective-C interfaces. Just return early and let
  // ActOnMemberReferenceExpr do the work.
  if (!BaseType->isRecordType()) {
    // C++ [basic.lookup.classref]p2:
    //   [...] If the type of the object expression is of pointer to scalar
    //   type, the unqualified-id is looked up in the context of the complete
    //   postfix-expression.
    //
    // This also indicates that we should be parsing a
    // pseudo-destructor-name.
    ObjectType = ParsedType();
    MayBePseudoDestructor = true;
    return Owned(Base);
  }

  // The object type must be complete (or dependent).
  if (!BaseType->isDependentType() &&
      RequireCompleteType(OpLoc, BaseType,
                          PDiag(diag::err_incomplete_member_access)))
    return ExprError();

  // C++ [basic.lookup.classref]p2:
  //   If the id-expression in a class member access (5.2.5) is an
  //   unqualified-id, and the type of the object expression is of a class
  //   type C (or of pointer to a class type C), the unqualified-id is looked
  //   up in the scope of class C. [...]
  ObjectType = ParsedType::make(BaseType);
  return move(Base);
}

ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
                                                   Expr *MemExpr) {
  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc);
  Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call)
    << isa<CXXPseudoDestructorExpr>(MemExpr)
    << FixItHint::CreateInsertion(ExpectedLParenLoc, "()");

  return ActOnCallExpr(/*Scope*/ 0,
                       MemExpr,
                       /*LPLoc*/ ExpectedLParenLoc,
                       MultiExprArg(),
                       /*RPLoc*/ ExpectedLParenLoc);
}

static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *Base, 
                   tok::TokenKind& OpKind, SourceLocation OpLoc) {
  // C++ [expr.pseudo]p2:
  //   The left-hand side of the dot operator shall be of scalar type. The
  //   left-hand side of the arrow operator shall be of pointer to scalar type.
  //   This scalar type is the object type.
  if (OpKind == tok::arrow) {
    if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
      ObjectType = Ptr->getPointeeType();
    } else if (!Base->isTypeDependent()) {
      // The user wrote "p->" when she probably meant "p."; fix it.
      S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
        << ObjectType << true
        << FixItHint::CreateReplacement(OpLoc, ".");
      if (S.isSFINAEContext())
        return true;

      OpKind = tok::period;
    }
  }

  return false;
}

ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
                                           SourceLocation OpLoc,
                                           tok::TokenKind OpKind,
                                           const CXXScopeSpec &SS,
                                           TypeSourceInfo *ScopeTypeInfo,
                                           SourceLocation CCLoc,
                                           SourceLocation TildeLoc,
                                         PseudoDestructorTypeStorage Destructed,
                                           bool HasTrailingLParen) {
  TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();

  QualType ObjectType = Base->getType();
  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
    return ExprError();

  if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) {
    Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
      << ObjectType << Base->getSourceRange();
    return ExprError();
  }

  // C++ [expr.pseudo]p2:
  //   [...] The cv-unqualified versions of the object type and of the type
  //   designated by the pseudo-destructor-name shall be the same type.
  if (DestructedTypeInfo) {
    QualType DestructedType = DestructedTypeInfo->getType();
    SourceLocation DestructedTypeStart
      = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin();
    if (!DestructedType->isDependentType() && !ObjectType->isDependentType()) {
      if (!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
        Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
          << ObjectType << DestructedType << Base->getSourceRange()
          << DestructedTypeInfo->getTypeLoc().getLocalSourceRange();

        // Recover by setting the destructed type to the object type.
        DestructedType = ObjectType;
        DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
                                                           DestructedTypeStart);
        Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
      } else if (DestructedType.getObjCLifetime() != 
                                                ObjectType.getObjCLifetime()) {
        
        if (DestructedType.getObjCLifetime() == Qualifiers::OCL_None) {
          // Okay: just pretend that the user provided the correctly-qualified
          // type.
        } else {
          Diag(DestructedTypeStart, diag::err_arc_pseudo_dtor_inconstant_quals)
            << ObjectType << DestructedType << Base->getSourceRange()
            << DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
        }
        
        // Recover by setting the destructed type to the object type.
        DestructedType = ObjectType;
        DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
                                                           DestructedTypeStart);
        Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
      }
    }
  }

  // C++ [expr.pseudo]p2:
  //   [...] Furthermore, the two type-names in a pseudo-destructor-name of the
  //   form
  //
  //     ::[opt] nested-name-specifier[opt] type-name :: ~ type-name
  //
  //   shall designate the same scalar type.
  if (ScopeTypeInfo) {
    QualType ScopeType = ScopeTypeInfo->getType();
    if (!ScopeType->isDependentType() && !ObjectType->isDependentType() &&
        !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) {

      Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(),
           diag::err_pseudo_dtor_type_mismatch)
        << ObjectType << ScopeType << Base->getSourceRange()
        << ScopeTypeInfo->getTypeLoc().getLocalSourceRange();

      ScopeType = QualType();
      ScopeTypeInfo = 0;
    }
  }

  Expr *Result
    = new (Context) CXXPseudoDestructorExpr(Context, Base,
                                            OpKind == tok::arrow, OpLoc,
                                            SS.getWithLocInContext(Context),
                                            ScopeTypeInfo,
                                            CCLoc,
                                            TildeLoc,
                                            Destructed);

  if (HasTrailingLParen)
    return Owned(Result);

  return DiagnoseDtorReference(Destructed.getLocation(), Result);
}

ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
                                           SourceLocation OpLoc,
                                           tok::TokenKind OpKind,
                                           CXXScopeSpec &SS,
                                           UnqualifiedId &FirstTypeName,
                                           SourceLocation CCLoc,
                                           SourceLocation TildeLoc,
                                           UnqualifiedId &SecondTypeName,
                                           bool HasTrailingLParen) {
  assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
          FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
         "Invalid first type name in pseudo-destructor");
  assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
          SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
         "Invalid second type name in pseudo-destructor");

  QualType ObjectType = Base->getType();
  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
    return ExprError();

  // Compute the object type that we should use for name lookup purposes. Only
  // record types and dependent types matter.
  ParsedType ObjectTypePtrForLookup;
  if (!SS.isSet()) {
    if (ObjectType->isRecordType())
      ObjectTypePtrForLookup = ParsedType::make(ObjectType);
    else if (ObjectType->isDependentType())
      ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
  }

  // Convert the name of the type being destructed (following the ~) into a
  // type (with source-location information).
  QualType DestructedType;
  TypeSourceInfo *DestructedTypeInfo = 0;
  PseudoDestructorTypeStorage Destructed;
  if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
    ParsedType T = getTypeName(*SecondTypeName.Identifier,
                               SecondTypeName.StartLocation,
                               S, &SS, true, false, ObjectTypePtrForLookup);
    if (!T &&
        ((SS.isSet() && !computeDeclContext(SS, false)) ||
         (!SS.isSet() && ObjectType->isDependentType()))) {
      // The name of the type being destroyed is a dependent name, and we
      // couldn't find anything useful in scope. Just store the identifier and
      // it's location, and we'll perform (qualified) name lookup again at
      // template instantiation time.
      Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
                                               SecondTypeName.StartLocation);
    } else if (!T) {
      Diag(SecondTypeName.StartLocation,
           diag::err_pseudo_dtor_destructor_non_type)
        << SecondTypeName.Identifier << ObjectType;
      if (isSFINAEContext())
        return ExprError();

      // Recover by assuming we had the right type all along.
      DestructedType = ObjectType;
    } else
      DestructedType = GetTypeFromParser(T, &DestructedTypeInfo);
  } else {
    // Resolve the template-id to a type.
    TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
    ASTTemplateArgsPtr TemplateArgsPtr(*this,
                                       TemplateId->getTemplateArgs(),
                                       TemplateId->NumArgs);
    TypeResult T = ActOnTemplateIdType(TemplateId->SS,
                                       TemplateId->Template,
                                       TemplateId->TemplateNameLoc,
                                       TemplateId->LAngleLoc,
                                       TemplateArgsPtr,
                                       TemplateId->RAngleLoc);
    if (T.isInvalid() || !T.get()) {
      // Recover by assuming we had the right type all along.
      DestructedType = ObjectType;
    } else
      DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo);
  }

  // If we've performed some kind of recovery, (re-)build the type source
  // information.
  if (!DestructedType.isNull()) {
    if (!DestructedTypeInfo)
      DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
                                                  SecondTypeName.StartLocation);
    Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
  }

  // Convert the name of the scope type (the type prior to '::') into a type.
  TypeSourceInfo *ScopeTypeInfo = 0;
  QualType ScopeType;
  if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
      FirstTypeName.Identifier) {
    if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
      ParsedType T = getTypeName(*FirstTypeName.Identifier,
                                 FirstTypeName.StartLocation,
                                 S, &SS, true, false, ObjectTypePtrForLookup);
      if (!T) {
        Diag(FirstTypeName.StartLocation,
             diag::err_pseudo_dtor_destructor_non_type)
          << FirstTypeName.Identifier << ObjectType;

        if (isSFINAEContext())
          return ExprError();

        // Just drop this type. It's unnecessary anyway.
        ScopeType = QualType();
      } else
        ScopeType = GetTypeFromParser(T, &ScopeTypeInfo);
    } else {
      // Resolve the template-id to a type.
      TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
      ASTTemplateArgsPtr TemplateArgsPtr(*this,
                                         TemplateId->getTemplateArgs(),
                                         TemplateId->NumArgs);
      TypeResult T = ActOnTemplateIdType(TemplateId->SS,
                                         TemplateId->Template,
                                         TemplateId->TemplateNameLoc,
                                         TemplateId->LAngleLoc,
                                         TemplateArgsPtr,
                                         TemplateId->RAngleLoc);
      if (T.isInvalid() || !T.get()) {
        // Recover by dropping this type.
        ScopeType = QualType();
      } else
        ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo);
    }
  }

  if (!ScopeType.isNull() && !ScopeTypeInfo)
    ScopeTypeInfo = Context.getTrivialTypeSourceInfo(ScopeType,
                                                  FirstTypeName.StartLocation);


  return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS,
                                   ScopeTypeInfo, CCLoc, TildeLoc,
                                   Destructed, HasTrailingLParen);
}

ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
                                           SourceLocation OpLoc,
                                           tok::TokenKind OpKind,
                                           SourceLocation TildeLoc, 
                                           const DeclSpec& DS,
                                           bool HasTrailingLParen) {
  
  QualType ObjectType = Base->getType();
  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
    return ExprError();

  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());

  TypeLocBuilder TLB;
  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
  DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
  TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T);
  PseudoDestructorTypeStorage Destructed(DestructedTypeInfo);

  return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(),
                                   0, SourceLocation(), TildeLoc,
                                   Destructed, HasTrailingLParen);
}

ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
                                        CXXMethodDecl *Method,
                                        bool HadMultipleCandidates) {
  ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0,
                                          FoundDecl, Method);
  if (Exp.isInvalid())
    return true;

  MemberExpr *ME =
      new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method,
                               SourceLocation(), Context.BoundMemberTy,
                               VK_RValue, OK_Ordinary);
  if (HadMultipleCandidates)
    ME->setHadMultipleCandidates(true);

  QualType ResultType = Method->getResultType();
  ExprValueKind VK = Expr::getValueKindForType(ResultType);
  ResultType = ResultType.getNonLValueExprType(Context);

  MarkDeclarationReferenced(Exp.get()->getLocStart(), Method);
  CXXMemberCallExpr *CE =
    new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
                                    Exp.get()->getLocEnd());
  return CE;
}

ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
                                      SourceLocation RParen) {
  return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
                                             Operand->CanThrow(Context),
                                             KeyLoc, RParen));
}

ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
                                   Expr *Operand, SourceLocation RParen) {
  return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen);
}

/// Perform the conversions required for an expression used in a
/// context that ignores the result.
ExprResult Sema::IgnoredValueConversions(Expr *E) {
  if (E->hasPlaceholderType()) {
    ExprResult result = CheckPlaceholderExpr(E);
    if (result.isInvalid()) return Owned(E);
    E = result.take();
  }

  // C99 6.3.2.1:
  //   [Except in specific positions,] an lvalue that does not have
  //   array type is converted to the value stored in the
  //   designated object (and is no longer an lvalue).
  if (E->isRValue()) {
    // In C, function designators (i.e. expressions of function type)
    // are r-values, but we still want to do function-to-pointer decay
    // on them.  This is both technically correct and convenient for
    // some clients.
    if (!getLangOptions().CPlusPlus && E->getType()->isFunctionType())
      return DefaultFunctionArrayConversion(E);

    return Owned(E);
  }

  // Otherwise, this rule does not apply in C++, at least not for the moment.
  if (getLangOptions().CPlusPlus) return Owned(E);

  // GCC seems to also exclude expressions of incomplete enum type.
  if (const EnumType *T = E->getType()->getAs<EnumType>()) {
    if (!T->getDecl()->isComplete()) {
      // FIXME: stupid workaround for a codegen bug!
      E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take();
      return Owned(E);
    }
  }

  ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
  if (Res.isInvalid())
    return Owned(E);
  E = Res.take();

  if (!E->getType()->isVoidType())
    RequireCompleteType(E->getExprLoc(), E->getType(),
                        diag::err_incomplete_type);
  return Owned(E);
}

ExprResult Sema::ActOnFinishFullExpr(Expr *FE) {
  ExprResult FullExpr = Owned(FE);

  if (!FullExpr.get())
    return ExprError();

  if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
    return ExprError();

  // Top-level message sends default to 'id' when we're in a debugger.
  if (getLangOptions().DebuggerSupport &&
      FullExpr.get()->getType() == Context.UnknownAnyTy &&
      isa<ObjCMessageExpr>(FullExpr.get())) {
    FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType());
    if (FullExpr.isInvalid())
      return ExprError();
  }
  
  FullExpr = CheckPlaceholderExpr(FullExpr.take());
  if (FullExpr.isInvalid())
    return ExprError();

  FullExpr = IgnoredValueConversions(FullExpr.take());
  if (FullExpr.isInvalid())
    return ExprError();

  CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc());
  return MaybeCreateExprWithCleanups(FullExpr);
}

StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
  if (!FullStmt) return StmtError();

  return MaybeCreateStmtWithCleanups(FullStmt);
}

Sema::IfExistsResult 
Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
                                   CXXScopeSpec &SS,
                                   const DeclarationNameInfo &TargetNameInfo) {
  DeclarationName TargetName = TargetNameInfo.getName();
  if (!TargetName)
    return IER_DoesNotExist;
  
  // If the name itself is dependent, then the result is dependent.
  if (TargetName.isDependentName())
    return IER_Dependent;
  
  // Do the redeclaration lookup in the current scope.
  LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
                 Sema::NotForRedeclaration);
  LookupParsedName(R, S, &SS);
  R.suppressDiagnostics();
  
  switch (R.getResultKind()) {
  case LookupResult::Found:
  case LookupResult::FoundOverloaded:
  case LookupResult::FoundUnresolvedValue:
  case LookupResult::Ambiguous:
    return IER_Exists;
    
  case LookupResult::NotFound:
    return IER_DoesNotExist;
    
  case LookupResult::NotFoundInCurrentInstantiation:
    return IER_Dependent;
  }
  
  return IER_DoesNotExist;  
}

Sema::IfExistsResult 
Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
                                   bool IsIfExists, CXXScopeSpec &SS,
                                   UnqualifiedId &Name) {
  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
  
  // Check for unexpanded parameter packs.
  SmallVector<UnexpandedParameterPack, 4> Unexpanded;
  collectUnexpandedParameterPacks(SS, Unexpanded);
  collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded);
  if (!Unexpanded.empty()) {
    DiagnoseUnexpandedParameterPacks(KeywordLoc,
                                     IsIfExists? UPPC_IfExists 
                                               : UPPC_IfNotExists, 
                                     Unexpanded);
    return IER_Error;
  }
  
  return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
}

//===----------------------------------------------------------------------===//
// Lambdas.
//===----------------------------------------------------------------------===//

void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                        Declarator &ParamInfo,
                                        Scope *CurScope) {
  DeclContext *DC = CurContext;
  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
    DC = DC->getParent();

  // Start constructing the lambda class.
  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
                                               Intro.Range.getBegin(),
                                               /*IdLoc=*/SourceLocation(),
                                               /*Id=*/0);
  Class->startDefinition();
  Class->setLambda(true);
  CurContext->addDecl(Class);

  QualType ThisCaptureType;
  llvm::SmallVector<LambdaScopeInfo::Capture, 4> Captures;
  llvm::DenseMap<const IdentifierInfo*, SourceLocation> CapturesSoFar;
  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
       C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; ++C) {
    if (C->Kind == LCK_This) {
      if (!ThisCaptureType.isNull()) {
        Diag(C->Loc, diag::err_capture_more_than_once) << "'this'";
        continue;
      }

      if (Intro.Default == LCD_ByCopy) {
        Diag(C->Loc, diag::err_this_capture_with_copy_default);
        continue;
      }

      ThisCaptureType = getCurrentThisType();
      if (ThisCaptureType.isNull()) {
        Diag(C->Loc, diag::err_invalid_this_use);
        continue;
      }
      CheckCXXThisCapture(C->Loc);

      Captures.push_back(LambdaScopeInfo::Capture::ThisCapture);
      continue;
    }

    assert(C->Id && "missing identifier for capture");

    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
      continue;
    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
      continue;
    }

    llvm::DenseMap<const IdentifierInfo*, SourceLocation>::iterator Appearance;
    bool IsFirstAppearance;
    llvm::tie(Appearance, IsFirstAppearance)
      = CapturesSoFar.insert(std::make_pair(C->Id, C->Loc));

    if (!IsFirstAppearance) {
      Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
      continue;
    }

    DeclarationNameInfo Name(C->Id, C->Loc);
    LookupResult R(*this, Name, LookupOrdinaryName);
    CXXScopeSpec ScopeSpec;
    LookupParsedName(R, CurScope, &ScopeSpec);
    if (R.isAmbiguous())
      continue;
    if (R.empty())
      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, CTC_Unknown))
        continue;

    VarDecl *Var = R.getAsSingle<VarDecl>();
    if (!Var) {
      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
      continue;
    }

    if (!Var->hasLocalStorage()) {
      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
      continue;
    }

    // FIXME: Actually capturing a variable is much more complicated than this
    // in the general case; see shouldCaptureValueReference.
    // FIXME: Should we be building a DeclRefExpr here?  We don't really need
    // it until the point where we're actually building the LambdaExpr.
    Captures.push_back(LambdaScopeInfo::Capture(Var, C->Kind));
  }

  // Build the call operator; we don't really have all the relevant information
  // at this point, but we need something to attach child declarations to.
  QualType MethodTy;
  TypeSourceInfo *MethodTyInfo;
  if (ParamInfo.getNumTypeObjects() == 0) {
    FunctionProtoType::ExtProtoInfo EPI;
    EPI.TypeQuals |= DeclSpec::TQ_const;
    MethodTy = Context.getFunctionType(Context.DependentTy,
                                       /*Args=*/0, /*NumArgs=*/0, EPI);
    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
  } else {
    assert(ParamInfo.isFunctionDeclarator() &&
           "lambda-declarator is a function");
    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
    if (!FTI.hasMutableQualifier())
      FTI.TypeQuals |= DeclSpec::TQ_const;
    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
    // FIXME: Can these asserts actually fail?
    assert(MethodTyInfo && "no type from lambda-declarator");
    MethodTy = MethodTyInfo->getType();
    assert(!MethodTy.isNull() && "no type from lambda declarator");
  }

  DeclarationName MethodName
    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
  CXXMethodDecl *Method
    = CXXMethodDecl::Create(Context,
                            Class,
                            ParamInfo.getSourceRange().getEnd(),
                            DeclarationNameInfo(MethodName,
                                                /*NameLoc=*/SourceLocation()),
                            MethodTy,
                            MethodTyInfo,
                            /*isStatic=*/false,
                            SC_None,
                            /*isInline=*/true,
                            /*isConstExpr=*/false,
                            ParamInfo.getSourceRange().getEnd());
  Method->setAccess(AS_public);
  Class->addDecl(Method);
  Method->setLexicalDeclContext(DC); // FIXME: Is this really correct?

  ProcessDeclAttributes(CurScope, Method, ParamInfo);

  // Enter a new evaluation context to insulate the block from any
  // cleanups from the enclosing full-expression.
  PushExpressionEvaluationContext(PotentiallyEvaluated);

  PushDeclContext(CurScope, Method);

  // Set the parameters on the decl, if specified.
  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
    FunctionProtoTypeLoc Proto =
        cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
    Method->setParams(Proto.getParams());
    CheckParmsForFunctionDef(Method->param_begin(),
                             Method->param_end(),
                             /*CheckParameterNames=*/false);

    // Introduce our parameters into the function scope
    for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
      ParmVarDecl *Param = Method->getParamDecl(p);
      Param->setOwningFunction(Method);

      // If this has an identifier, add it to the scope stack.
      if (Param->getIdentifier()) {
        CheckShadow(CurScope, Param);

        PushOnScopeChains(Param, CurScope);
      }
    }
  }

  // Introduce the lambda scope.
  PushLambdaScope(Class);

  LambdaScopeInfo *LSI = getCurLambda();
  LSI->Default = Intro.Default;
  if (!ThisCaptureType.isNull())
    LSI->CapturesCXXThis = true;
  std::swap(LSI->Captures, Captures);

  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
  QualType RetTy = Fn->getResultType();
  if (RetTy != Context.DependentTy) {
    LSI->ReturnType = RetTy;
    LSI->HasImplicitReturnType = true;
  }

  // FIXME: Check return type is complete, !isObjCObjectType
  
}

void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
  // Leave the expression-evaluation context.
  DiscardCleanupsInEvaluationContext();
  PopExpressionEvaluationContext();

  // Leave the context of the lambda.
  PopDeclContext();
  PopFunctionScopeInfo();
}

ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
                                 Stmt *Body, Scope *CurScope) {
  // FIXME: Implement
  Diag(StartLoc, diag::err_lambda_unsupported);
  ActOnLambdaError(StartLoc, CurScope);
  return ExprError();
}
