r183872 - PR12086, PR15117

Lang Hames lhames at gmail.com
Thu Jun 13 14:58:25 PDT 2013


Hi Richard,

It looks like this broke CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp

See - http://lab.llvm.org:8013/builders/clang-x86_64-darwin11-R/builds/1159

Cheers,
Lang.



On Wed, Jun 12, 2013 at 3:31 PM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:

> Author: rsmith
> Date: Wed Jun 12 17:31:48 2013
> New Revision: 183872
>
> URL: http://llvm.org/viewvc/llvm-project?rev=183872&view=rev
> Log:
> PR12086, PR15117
>
> Introduce CXXStdInitializerListExpr node, representing the implicit
> construction of a std::initializer_list<T> object from its underlying
> array.
> The AST representation of such an expression goes from an InitListExpr
> with a
> flag set, to a CXXStdInitializerListExpr containing a
> MaterializeTemporaryExpr
> containing an InitListExpr (possibly wrapped in a CXXBindTemporaryExpr).
>
> This more detailed representation has several advantages, the most
> important of
> which is that the new MaterializeTemporaryExpr allows us to directly model
> lifetime extension of the underlying temporary array. Using that, this
> patch
> *drastically* simplifies the IR generation of this construct, provides IR
> generation support for nested global initializer_list objects, fixes
> several
> bugs where the destructors for the underlying array would accidentally not
> get
> invoked, and provides constant expression evaluation support for
> std::initializer_list objects.
>
> Modified:
>     cfe/trunk/include/clang/AST/Expr.h
>     cfe/trunk/include/clang/AST/ExprCXX.h
>     cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>     cfe/trunk/include/clang/AST/Stmt.h
>     cfe/trunk/include/clang/Basic/StmtNodes.td
>     cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>     cfe/trunk/lib/AST/Expr.cpp
>     cfe/trunk/lib/AST/ExprClassification.cpp
>     cfe/trunk/lib/AST/ExprConstant.cpp
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/lib/AST/StmtPrinter.cpp
>     cfe/trunk/lib/AST/StmtProfile.cpp
>     cfe/trunk/lib/CodeGen/CGClass.cpp
>     cfe/trunk/lib/CodeGen/CGDecl.cpp
>     cfe/trunk/lib/CodeGen/CGExpr.cpp
>     cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>     cfe/trunk/lib/CodeGen/CGExprConstant.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.h
>     cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>     cfe/trunk/lib/CodeGen/CodeGenModule.h
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
>     cfe/trunk/lib/Sema/SemaInit.cpp
>     cfe/trunk/lib/Sema/TreeTransform.h
>     cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
>     cfe/trunk/lib/Serialization/ASTWriter.cpp
>     cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
>     cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
>     cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp
>
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
>
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
>     cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>     cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>     cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp
>     cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
>     cfe/trunk/tools/libclang/CXCursor.cpp
>     cfe/trunk/tools/libclang/RecursiveASTVisitor.h
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Wed Jun 12 17:31:48 2013
> @@ -3794,13 +3794,6 @@ public:
>      InitListExprBits.HadArrayRangeDesignator = ARD;
>    }
>
> -  bool initializesStdInitializerList() const {
> -    return InitListExprBits.InitializesStdInitializerList != 0;
> -  }
> -  void setInitializesStdInitializerList(bool ISIL = true) {
> -    InitListExprBits.InitializesStdInitializerList = ISIL;
> -  }
> -
>    SourceLocation getLocStart() const LLVM_READONLY;
>    SourceLocation getLocEnd() const LLVM_READONLY;
>
>
> Modified: cfe/trunk/include/clang/AST/ExprCXX.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)
> +++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Jun 12 17:31:48 2013
> @@ -474,6 +474,45 @@ public:
>    child_range children() { return child_range(); }
>  };
>
> +/// \brief Implicit construction of a std::initializer_list<T> object
> from an
> +/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
> +class CXXStdInitializerListExpr : public Expr {
> +  Stmt *SubExpr;
> +
> +  CXXStdInitializerListExpr(EmptyShell Empty)
> +    : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {}
> +
> +public:
> +  CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
> +    : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
> +           Ty->isDependentType(), SubExpr->isValueDependent(),
> +           SubExpr->isInstantiationDependent(),
> +           SubExpr->containsUnexpandedParameterPack()),
> +      SubExpr(SubExpr) {}
> +
> +  Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
> +  const Expr *getSubExpr() const { return static_cast<const
> Expr*>(SubExpr); }
> +
> +  SourceLocation getLocStart() const LLVM_READONLY {
> +    return SubExpr->getLocStart();
> +  }
> +  SourceLocation getLocEnd() const LLVM_READONLY {
> +    return SubExpr->getLocEnd();
> +  }
> +  SourceRange getSourceRange() const LLVM_READONLY {
> +    return SubExpr->getSourceRange();
> +  }
> +
> +  static bool classof(const Stmt *S) {
> +    return S->getStmtClass() == CXXStdInitializerListExprClass;
> +  }
> +
> +  child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
> +
> +  friend class ASTReader;
> +  friend class ASTStmtReader;
> +};
> +
>  /// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which
> gets
>  /// the type_info that corresponds to the supplied type, or the (possibly
>  /// dynamic) type of the supplied expression.
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Jun 12 17:31:48
> 2013
> @@ -2177,6 +2177,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {
>  DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
>  DEF_TRAVERSE_STMT(ExprWithCleanups, { })
>  DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
> +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { })
>  DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
>    TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
>    if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
>
> Modified: cfe/trunk/include/clang/AST/Stmt.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Stmt.h (original)
> +++ cfe/trunk/include/clang/AST/Stmt.h Wed Jun 12 17:31:48 2013
> @@ -266,10 +266,6 @@ protected:
>      /// Whether this initializer list originally had a GNU array-range
>      /// designator in it. This is a temporary marker used by CodeGen.
>      unsigned HadArrayRangeDesignator : 1;
> -
> -    /// Whether this initializer list initializes a std::initializer_list
> -    /// object.
> -    unsigned InitializesStdInitializerList : 1;
>    };
>
>    class TypeTraitExprBitfields {
>
> Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/StmtNodes.td Wed Jun 12 17:31:48 2013
> @@ -110,6 +110,7 @@ def CXXThrowExpr : DStmt<Expr>;
>  def CXXDefaultArgExpr : DStmt<Expr>;
>  def CXXDefaultInitExpr : DStmt<Expr>;
>  def CXXScalarValueInitExpr : DStmt<Expr>;
> +def CXXStdInitializerListExpr : DStmt<Expr>;
>  def CXXNewExpr : DStmt<Expr>;
>  def CXXDeleteExpr : DStmt<Expr>;
>  def CXXPseudoDestructorExpr : DStmt<Expr>;
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed Jun 12
> 17:31:48 2013
> @@ -1259,6 +1259,8 @@ namespace clang {
>        EXPR_CXX_FUNCTIONAL_CAST,
>        /// \brief A UserDefinedLiteral record.
>        EXPR_USER_DEFINED_LITERAL,
> +      /// \brief A CXXStdInitializerListExpr record.
> +      EXPR_CXX_STD_INITIALIZER_LIST,
>        /// \brief A CXXBoolLiteralExpr record.
>        EXPR_CXX_BOOL_LITERAL,
>        EXPR_CXX_NULL_PTR_LITERAL,  // CXXNullPtrLiteralExpr
>
> Modified: cfe/trunk/lib/AST/Expr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Expr.cpp (original)
> +++ cfe/trunk/lib/AST/Expr.cpp Wed Jun 12 17:31:48 2013
> @@ -1789,7 +1789,6 @@ InitListExpr::InitListExpr(ASTContext &C
>      LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(0, true)
>  {
>    sawArrayRangeDesignator(false);
> -  setInitializesStdInitializerList(false);
>    for (unsigned I = 0; I != initExprs.size(); ++I) {
>      if (initExprs[I]->isTypeDependent())
>        ExprBits.TypeDependent = true;
> @@ -2836,6 +2835,7 @@ bool Expr::HasSideEffects(const ASTConte
>    case DesignatedInitExprClass:
>    case ParenListExprClass:
>    case CXXPseudoDestructorExprClass:
> +  case CXXStdInitializerListExprClass:
>    case SubstNonTypeTemplateParmExprClass:
>    case MaterializeTemporaryExprClass:
>    case ShuffleVectorExprClass:
>
> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
> +++ cfe/trunk/lib/AST/ExprClassification.cpp Wed Jun 12 17:31:48 2013
> @@ -353,6 +353,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
>    case Expr::CXXConstructExprClass:
>    case Expr::CXXTemporaryObjectExprClass:
>    case Expr::LambdaExprClass:
> +  case Expr::CXXStdInitializerListExprClass:
>      return Cl::CL_ClassTemporary;
>
>    case Expr::VAArgExprClass:
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Jun 12 17:31:48 2013
> @@ -4576,6 +4576,7 @@ namespace {
>      bool VisitCastExpr(const CastExpr *E);
>      bool VisitInitListExpr(const InitListExpr *E);
>      bool VisitCXXConstructExpr(const CXXConstructExpr *E);
> +    bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr
> *E);
>    };
>  }
>
> @@ -4691,10 +4692,6 @@ bool RecordExprEvaluator::VisitCastExpr(
>  }
>
>  bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
> -  // Cannot constant-evaluate std::initializer_list inits.
> -  if (E->initializesStdInitializerList())
> -    return false;
> -
>    const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
>    if (RD->isInvalidDecl()) return false;
>    const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
> @@ -4810,6 +4807,58 @@ bool RecordExprEvaluator::VisitCXXConstr
>                                 Result);
>  }
>
> +bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
> +    const CXXStdInitializerListExpr *E) {
> +  const ConstantArrayType *ArrayType =
> +      Info.Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
> +
> +  LValue Array;
> +  if (!EvaluateLValue(E->getSubExpr(), Array, Info))
> +    return false;
> +
> +  // Get a pointer to the first element of the array.
> +  Array.addArray(Info, E, ArrayType);
> +
> +  // FIXME: Perform the checks on the field types in SemaInit.
> +  RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
> +  RecordDecl::field_iterator Field = Record->field_begin();
> +  if (Field == Record->field_end())
> +    return Error(E);
> +
> +  // Start pointer.
> +  if (!Field->getType()->isPointerType() ||
> +      !Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
> +                            ArrayType->getElementType()))
> +    return Error(E);
> +
> +  // FIXME: What if the initializer_list type has base classes, etc?
> +  Result = APValue(APValue::UninitStruct(), 0, 2);
> +  Array.moveInto(Result.getStructField(0));
> +
> +  if (++Field == Record->field_end())
> +    return Error(E);
> +
> +  if (Field->getType()->isPointerType() &&
> +      Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
> +                           ArrayType->getElementType())) {
> +    // End pointer.
> +    if (!HandleLValueArrayAdjustment(Info, E, Array,
> +                                     ArrayType->getElementType(),
> +                                     ArrayType->getSize().getZExtValue()))
> +      return false;
> +    Array.moveInto(Result.getStructField(1));
> +  } else if (Info.Ctx.hasSameType(Field->getType(),
> Info.Ctx.getSizeType()))
> +    // Length.
> +    Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
> +  else
> +    return Error(E);
> +
> +  if (++Field != Record->field_end())
> +    return Error(E);
> +
> +  return true;
> +}
> +
>  static bool EvaluateRecord(const Expr *E, const LValue &This,
>                             APValue &Result, EvalInfo &Info) {
>    assert(E->isRValue() && E->getType()->isRecordType() &&
> @@ -7762,6 +7811,7 @@ static ICEDiag CheckICE(const Expr* E, A
>    case Expr::UnresolvedLookupExprClass:
>    case Expr::DependentScopeDeclRefExprClass:
>    case Expr::CXXConstructExprClass:
> +  case Expr::CXXStdInitializerListExprClass:
>    case Expr::CXXBindTemporaryExprClass:
>    case Expr::ExprWithCleanupsClass:
>    case Expr::CXXTemporaryObjectExprClass:
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Jun 12 17:31:48 2013
> @@ -2481,6 +2481,10 @@ recurse:
>      mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity);
>      break;
>
> +  case Expr::CXXStdInitializerListExprClass:
> +    mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(),
> Arity);
> +    break;
> +
>    case Expr::SubstNonTypeTemplateParmExprClass:
>
>  mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
>                       Arity);
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Jun 12 17:31:48 2013
> @@ -1534,6 +1534,10 @@ void StmtPrinter::VisitCXXConstructExpr(
>      OS << " }";
>  }
>
> +void
> StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
> +  PrintExpr(E->getSubExpr());
> +}
> +
>  void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) {
>    // Just forward to the sub expression.
>    PrintExpr(E->getSubExpr());
>
> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
> +++ cfe/trunk/lib/AST/StmtProfile.cpp Wed Jun 12 17:31:48 2013
> @@ -758,6 +758,11 @@ void StmtProfiler::VisitCXXNullPtrLitera
>    VisitExpr(S);
>  }
>
> +void StmtProfiler::VisitCXXStdInitializerListExpr(
> +    const CXXStdInitializerListExpr *S) {
> +  VisitExpr(S);
> +}
> +
>  void StmtProfiler::VisitCXXTypeidExpr(const CXXTypeidExpr *S) {
>    VisitExpr(S);
>    if (S->isTypeOperand())
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Jun 12 17:31:48 2013
> @@ -433,52 +433,45 @@ static void EmitAggMemberInitializer(Cod
>                                       unsigned Index) {
>    if (Index == ArrayIndexes.size()) {
>      LValue LV = LHS;
> -    { // Scope for Cleanups.
> -      CodeGenFunction::RunCleanupsScope Cleanups(CGF);
>
> -      if (ArrayIndexVar) {
> -        // If we have an array index variable, load it and use it as an
> offset.
> -        // Then, increment the value.
> -        llvm::Value *Dest = LHS.getAddress();
> -        llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
> -        Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex,
> "destaddress");
> -        llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(),
> 1);
> -        Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
> -        CGF.Builder.CreateStore(Next, ArrayIndexVar);
> -
> -        // Update the LValue.
> -        LV.setAddress(Dest);
> -        CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
> -        LV.setAlignment(std::min(Align, LV.getAlignment()));
> -      }
> -
> -      switch (CGF.getEvaluationKind(T)) {
> -      case TEK_Scalar:
> -        CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
> -        break;
> -      case TEK_Complex:
> -        CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
> -        break;
> -      case TEK_Aggregate: {
> -        AggValueSlot Slot =
> -          AggValueSlot::forLValue(LV,
> -                                  AggValueSlot::IsDestructed,
> -                                  AggValueSlot::DoesNotNeedGCBarriers,
> -                                  AggValueSlot::IsNotAliased);
> -
> -        CGF.EmitAggExpr(Init, Slot);
> -        break;
> -      }
> -      }
> +    if (ArrayIndexVar) {
> +      // If we have an array index variable, load it and use it as an
> offset.
> +      // Then, increment the value.
> +      llvm::Value *Dest = LHS.getAddress();
> +      llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
> +      Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex,
> "destaddress");
> +      llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(),
> 1);
> +      Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
> +      CGF.Builder.CreateStore(Next, ArrayIndexVar);
> +
> +      // Update the LValue.
> +      LV.setAddress(Dest);
> +      CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
> +      LV.setAlignment(std::min(Align, LV.getAlignment()));
>      }
>
> -    // Now, outside of the initializer cleanup scope, destroy the backing
> array
> -    // for a std::initializer_list member.
> -    CGF.MaybeEmitStdInitializerListCleanup(LV.getAddress(), Init);
> +    switch (CGF.getEvaluationKind(T)) {
> +    case TEK_Scalar:
> +      CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
> +      break;
> +    case TEK_Complex:
> +      CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
> +      break;
> +    case TEK_Aggregate: {
> +      AggValueSlot Slot =
> +        AggValueSlot::forLValue(LV,
> +                                AggValueSlot::IsDestructed,
> +                                AggValueSlot::DoesNotNeedGCBarriers,
> +                                AggValueSlot::IsNotAliased);
> +
> +      CGF.EmitAggExpr(Init, Slot);
> +      break;
> +    }
> +    }
>
>      return;
>    }
> -
> +
>    const ConstantArrayType *Array =
> CGF.getContext().getAsConstantArrayType(T);
>    assert(Array && "Array initialization without the array type?");
>    llvm::Value *IndexVar
> @@ -512,16 +505,12 @@ static void EmitAggMemberInitializer(Cod
>
>    CGF.EmitBlock(ForBody);
>    llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
> -
> -  {
> -    CodeGenFunction::RunCleanupsScope Cleanups(CGF);
> -
> -    // Inside the loop body recurse to emit the inner loop or,
> eventually, the
> -    // constructor call.
> -    EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar,
> -                             Array->getElementType(), ArrayIndexes, Index
> + 1);
> -  }
> -
> +
> +  // Inside the loop body recurse to emit the inner loop or, eventually,
> the
> +  // constructor call.
> +  EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar,
> +                           Array->getElementType(), ArrayIndexes, Index +
> 1);
> +
>    CGF.EmitBlock(ContinueBlock);
>
>    // Emit the increment of the loop counter.
> @@ -726,7 +715,7 @@ void CodeGenFunction::EmitConstructorBod
>    if (IsTryBody)
>      EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
>
> -  EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
> +  RunCleanupsScope RunCleanups(*this);
>
>    // TODO: in restricted cases, we can emit the vbase initializers of
>    // a complete ctor and then delegate to the base ctor.
> @@ -745,7 +734,7 @@ void CodeGenFunction::EmitConstructorBod
>    // initializers, which includes (along the exceptional path) the
>    // destructors for those members and bases that were fully
>    // constructed.
> -  PopCleanupBlocks(CleanupDepth);
> +  RunCleanups.ForceCleanup();
>
>    if (IsTryBody)
>      ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Wed Jun 12 17:31:48 2013
> @@ -1187,7 +1187,6 @@ void CodeGenFunction::EmitExprAsInit(con
>
> AggValueSlot::DoesNotNeedGCBarriers,
>
>  AggValueSlot::IsNotAliased));
>      }
> -    MaybeEmitStdInitializerListCleanup(lvalue.getAddress(), init);
>      return;
>    }
>    llvm_unreachable("bad evaluation kind");
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Wed Jun 12 17:31:48 2013
> @@ -240,15 +240,6 @@ pushTemporaryCleanup(CodeGenFunction &CG
>      }
>    }
>
> -  if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
> -    if (ILE->initializesStdInitializerList()) {
> -      // FIXME: This is wrong if the temporary has static or thread
> storage
> -      // duration.
> -      CGF.EmitStdInitializerListCleanup(ReferenceTemporary, ILE);
> -      return;
> -    }
> -  }
> -
>    CXXDestructorDecl *ReferenceTemporaryDtor = 0;
>    if (const RecordType *RT =
>            E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Jun 12 17:31:48 2013
> @@ -91,7 +91,6 @@ public:
>
>    void EmitMoveFromReturnSlot(const Expr *E, RValue Src);
>
> -  void EmitStdInitializerList(llvm::Value *DestPtr, InitListExpr
> *InitList);
>    void EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
>                       QualType elementType, InitListExpr *E);
>
> @@ -177,6 +176,7 @@ public:
>    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
>    void VisitCXXConstructExpr(const CXXConstructExpr *E);
>    void VisitLambdaExpr(LambdaExpr *E);
> +  void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
>    void VisitExprWithCleanups(ExprWithCleanups *E);
>    void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
>    void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
> @@ -345,89 +345,70 @@ void AggExprEmitter::EmitCopy(QualType t
>                          std::min(dest.getAlignment(),
> src.getAlignment()));
>  }
>
> -static QualType GetStdInitializerListElementType(QualType T) {
> -  // Just assume that this is really std::initializer_list.
> -  ClassTemplateSpecializationDecl *specialization =
> -
>  cast<ClassTemplateSpecializationDecl>(T->castAs<RecordType>()->getDecl());
> -  return specialization->getTemplateArgs()[0].getAsType();
> -}
> -
> -/// \brief Prepare cleanup for the temporary array.
> -static void EmitStdInitializerListCleanup(CodeGenFunction &CGF,
> -                                          QualType arrayType,
> -                                          llvm::Value *addr,
> -                                          const InitListExpr *initList) {
> -  QualType::DestructionKind dtorKind = arrayType.isDestructedType();
> -  if (!dtorKind)
> -    return; // Type doesn't need destroying.
> -  if (dtorKind != QualType::DK_cxx_destructor) {
> -    CGF.ErrorUnsupported(initList, "ObjC ARC type in initializer_list");
> -    return;
> -  }
> -
> -  CodeGenFunction::Destroyer *destroyer = CGF.getDestroyer(dtorKind);
> -  CGF.pushDestroy(NormalAndEHCleanup, addr, arrayType, destroyer,
> -                  /*EHCleanup=*/true);
> -}
> -
>  /// \brief Emit the initializer for a std::initializer_list initialized
> with a
>  /// real initializer list.
> -void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
> -                                            InitListExpr *initList) {
> -  // We emit an array containing the elements, then have the init list
> point
> -  // at the array.
> -  ASTContext &ctx = CGF.getContext();
> -  unsigned numInits = initList->getNumInits();
> -  QualType element =
> GetStdInitializerListElementType(initList->getType());
> -  llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits);
> -  QualType array = ctx.getConstantArrayType(element, size,
> ArrayType::Normal,0);
> -  llvm::Type *LTy = CGF.ConvertTypeForMem(array);
> -  llvm::AllocaInst *alloc = CGF.CreateTempAlloca(LTy);
> -  alloc->setAlignment(ctx.getTypeAlignInChars(array).getQuantity());
> -  alloc->setName(".initlist.");
> -
> -  EmitArrayInit(alloc, cast<llvm::ArrayType>(LTy), element, initList);
> -
> -  // FIXME: The diagnostics are somewhat out of place here.
> -  RecordDecl *record =
> initList->getType()->castAs<RecordType>()->getDecl();
> -  RecordDecl::field_iterator field = record->field_begin();
> -  if (field == record->field_end()) {
> -    CGF.ErrorUnsupported(initList, "weird std::initializer_list");
> +void
> +AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr
> *E) {
> +  // Emit an array containing the elements.  The array is externally
> destructed
> +  // if the std::initializer_list object is.
> +  ASTContext &Ctx = CGF.getContext();
> +  LValue Array = CGF.EmitLValue(E->getSubExpr());
> +  assert(Array.isSimple() && "initializer_list array not a simple
> lvalue");
> +  llvm::Value *ArrayPtr = Array.getAddress();
> +
> +  const ConstantArrayType *ArrayType =
> +      Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
> +  assert(ArrayType && "std::initializer_list constructed from non-array");
> +
> +  // FIXME: Perform the checks on the field types in SemaInit.
> +  RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
> +  RecordDecl::field_iterator Field = Record->field_begin();
> +  if (Field == Record->field_end()) {
> +    CGF.ErrorUnsupported(E, "weird std::initializer_list");
>      return;
>    }
>
> -  QualType elementPtr = ctx.getPointerType(element.withConst());
> -
>    // Start pointer.
> -  if (!ctx.hasSameType(field->getType(), elementPtr)) {
> -    CGF.ErrorUnsupported(initList, "weird std::initializer_list");
> +  if (!Field->getType()->isPointerType() ||
> +      !Ctx.hasSameType(Field->getType()->getPointeeType(),
> +                       ArrayType->getElementType())) {
> +    CGF.ErrorUnsupported(E, "weird std::initializer_list");
>      return;
>    }
> -  LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr,
> initList->getType());
> -  LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field);
> -  llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0,
> "arraystart");
> -  CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start);
> -  ++field;
>
> -  if (field == record->field_end()) {
> -    CGF.ErrorUnsupported(initList, "weird std::initializer_list");
> +  AggValueSlot Dest = EnsureSlot(E->getType());
> +  LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
> +                                     Dest.getAlignment());
> +  LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
> +  llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
> +  llvm::Value *IdxStart[] = { Zero, Zero };
> +  llvm::Value *ArrayStart =
> +      Builder.CreateInBoundsGEP(ArrayPtr, IdxStart, "arraystart");
> +  CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
> +  ++Field;
> +
> +  if (Field == Record->field_end()) {
> +    CGF.ErrorUnsupported(E, "weird std::initializer_list");
>      return;
>    }
> -  LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV,
> *field);
> -  if (ctx.hasSameType(field->getType(), elementPtr)) {
> +
> +  llvm::Value *Size = Builder.getInt(ArrayType->getSize());
> +  LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV,
> *Field);
> +  if (Field->getType()->isPointerType() &&
> +      Ctx.hasSameType(Field->getType()->getPointeeType(),
> +                      ArrayType->getElementType())) {
>      // End pointer.
> -    llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits,
> "arrayend");
> -    CGF.EmitStoreThroughLValue(RValue::get(arrayEnd), endOrLength);
> -  } else if(ctx.hasSameType(field->getType(), ctx.getSizeType())) {
> +    llvm::Value *IdxEnd[] = { Zero, Size };
> +    llvm::Value *ArrayEnd =
> +        Builder.CreateInBoundsGEP(ArrayPtr, IdxEnd, "arrayend");
> +    CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength);
> +  } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
>      // Length.
> -    CGF.EmitStoreThroughLValue(RValue::get(Builder.getInt(size)),
> endOrLength);
> +    CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength);
>    } else {
> -    CGF.ErrorUnsupported(initList, "weird std::initializer_list");
> +    CGF.ErrorUnsupported(E, "weird std::initializer_list");
>      return;
>    }
> -
> -  if (!Dest.isExternallyDestructed())
> -    EmitStdInitializerListCleanup(CGF, array, alloc, initList);
>  }
>
>  /// \brief Emit initialization of an array from an initializer list.
> @@ -490,15 +471,8 @@ void AggExprEmitter::EmitArrayInit(llvm:
>        if (endOfInit) Builder.CreateStore(element, endOfInit);
>      }
>
> -    // If these are nested std::initializer_list inits, do them directly,
> -    // because they are conceptually the same "location".
> -    InitListExpr *initList = dyn_cast<InitListExpr>(E->getInit(i));
> -    if (initList && initList->initializesStdInitializerList()) {
> -      EmitStdInitializerList(element, initList);
> -    } else {
> -      LValue elementLV = CGF.MakeAddrLValue(element, elementType);
> -      EmitInitializationToLValue(E->getInit(i), elementLV);
> -    }
> +    LValue elementLV = CGF.MakeAddrLValue(element, elementType);
> +    EmitInitializationToLValue(E->getInit(i), elementLV);
>    }
>
>    // Check whether there's a non-trivial array-fill expression.
> @@ -1161,11 +1135,6 @@ void AggExprEmitter::VisitInitListExpr(I
>
>    AggValueSlot Dest = EnsureSlot(E->getType());
>
> -  if (E->initializesStdInitializerList()) {
> -    EmitStdInitializerList(Dest.getAddr(), E);
> -    return;
> -  }
> -
>    LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
>                                       Dest.getAlignment());
>
> @@ -1546,58 +1515,3 @@ void CodeGenFunction::EmitAggregateCopy(
>                         alignment.getQuantity(), isVolatile,
>                         /*TBAATag=*/0, TBAAStructTag);
>  }
> -
> -void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc,
> -                                                         const Expr
> *init) {
> -  const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(init);
> -  if (cleanups)
> -    init = cleanups->getSubExpr();
> -
> -  if (isa<InitListExpr>(init) &&
> -      cast<InitListExpr>(init)->initializesStdInitializerList()) {
> -    // We initialized this std::initializer_list with an initializer list.
> -    // A backing array was created. Push a cleanup for it.
> -    EmitStdInitializerListCleanup(loc, cast<InitListExpr>(init));
> -  }
> -}
> -
> -static void EmitRecursiveStdInitializerListCleanup(CodeGenFunction &CGF,
> -                                                   llvm::Value
> *arrayStart,
> -                                                   const InitListExpr
> *init) {
> -  // Check if there are any recursive cleanups to do, i.e. if we have
> -  //   std::initializer_list<std::initializer_list<obj>> list = {{obj()}};
> -  // then we need to destroy the inner array as well.
> -  for (unsigned i = 0, e = init->getNumInits(); i != e; ++i) {
> -    const InitListExpr *subInit =
> dyn_cast<InitListExpr>(init->getInit(i));
> -    if (!subInit || !subInit->initializesStdInitializerList())
> -      continue;
> -
> -    // This one needs to be destroyed. Get the address of the
> std::init_list.
> -    llvm::Value *offset = llvm::ConstantInt::get(CGF.SizeTy, i);
> -    llvm::Value *loc = CGF.Builder.CreateInBoundsGEP(arrayStart, offset,
> -                                                 "std.initlist");
> -    CGF.EmitStdInitializerListCleanup(loc, subInit);
> -  }
> -}
> -
> -void CodeGenFunction::EmitStdInitializerListCleanup(llvm::Value *loc,
> -                                                    const InitListExpr
> *init) {
> -  ASTContext &ctx = getContext();
> -  QualType element = GetStdInitializerListElementType(init->getType());
> -  unsigned numInits = init->getNumInits();
> -  llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits);
> -  QualType array =ctx.getConstantArrayType(element, size,
> ArrayType::Normal, 0);
> -  QualType arrayPtr = ctx.getPointerType(array);
> -  llvm::Type *arrayPtrType = ConvertType(arrayPtr);
> -
> -  // lvalue is the location of a std::initializer_list, which as its first
> -  // element has a pointer to the array we want to destroy.
> -  llvm::Value *startPointer = Builder.CreateStructGEP(loc, 0,
> "startPointer");
> -  llvm::Value *startAddress = Builder.CreateLoad(startPointer,
> "startAddress");
> -
> -  ::EmitRecursiveStdInitializerListCleanup(*this, startAddress, init);
> -
> -  llvm::Value *arrayAddress =
> -      Builder.CreateBitCast(startAddress, arrayPtrType, "arrayAddress");
> -  ::EmitStdInitializerListCleanup(*this, array, arrayAddress, init);
> -}
>
> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Jun 12 17:31:48 2013
> @@ -838,8 +838,6 @@ static void StoreAnyExprIntoOneUnit(Code
>                                AggValueSlot::DoesNotNeedGCBarriers,
>                                AggValueSlot::IsNotAliased);
>      CGF.EmitAggExpr(Init, Slot);
> -
> -    CGF.MaybeEmitStdInitializerListCleanup(NewPtr, Init);
>      return;
>    }
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Jun 12 17:31:48 2013
> @@ -368,11 +368,6 @@ void ConstStructBuilder::ConvertStructTo
>  }
>
>  bool ConstStructBuilder::Build(InitListExpr *ILE) {
> -  if (ILE->initializesStdInitializerList()) {
> -    //CGM.ErrorUnsupported(ILE, "global std::initializer_list");
> -    return false;
> -  }
> -
>    RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
>    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Jun 12 17:31:48 2013
> @@ -1631,10 +1631,6 @@ public:
>    llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr
> *DCE);
>    llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
>
> -  void MaybeEmitStdInitializerListCleanup(llvm::Value *loc, const Expr
> *init);
> -  void EmitStdInitializerListCleanup(llvm::Value *loc,
> -                                     const InitListExpr *init);
> -
>    /// \brief Situations in which we might emit a check for the
> suitability of a
>    ///        pointer or glvalue.
>    enum TypeCheckKind {
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Jun 12 17:31:48 2013
> @@ -1628,125 +1628,6 @@ CharUnits CodeGenModule::GetTargetTypeSt
>        TheDataLayout.getTypeStoreSizeInBits(Ty));
>  }
>
> -llvm::Constant *
> -CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl
> *D,
> -                                                       const Expr
> *rawInit) {
> -  ArrayRef<ExprWithCleanups::CleanupObject> cleanups;
> -  if (const ExprWithCleanups *withCleanups =
> -          dyn_cast<ExprWithCleanups>(rawInit)) {
> -    cleanups = withCleanups->getObjects();
> -    rawInit = withCleanups->getSubExpr();
> -  }
> -
> -  const InitListExpr *init = dyn_cast<InitListExpr>(rawInit);
> -  if (!init || !init->initializesStdInitializerList() ||
> -      init->getNumInits() == 0)
> -    return 0;
> -
> -  ASTContext &ctx = getContext();
> -  unsigned numInits = init->getNumInits();
> -  // FIXME: This check is here because we would otherwise silently
> miscompile
> -  // nested global std::initializer_lists. Better would be to have a real
> -  // implementation.
> -  for (unsigned i = 0; i < numInits; ++i) {
> -    const InitListExpr *inner = dyn_cast<InitListExpr>(init->getInit(i));
> -    if (inner && inner->initializesStdInitializerList()) {
> -      ErrorUnsupported(inner, "nested global std::initializer_list");
> -      return 0;
> -    }
> -  }
> -
> -  // Synthesize a fake VarDecl for the array and initialize that.
> -  QualType elementType = init->getInit(0)->getType();
> -  llvm::APInt numElements(ctx.getTypeSize(ctx.getSizeType()), numInits);
> -  QualType arrayType = ctx.getConstantArrayType(elementType, numElements,
> -                                                ArrayType::Normal, 0);
> -
> -  IdentifierInfo *name = &ctx.Idents.get(D->getNameAsString() +
> "__initlist");
> -  TypeSourceInfo *sourceInfo = ctx.getTrivialTypeSourceInfo(
> -                                              arrayType,
> D->getLocation());
> -  VarDecl *backingArray = VarDecl::Create(ctx, const_cast<DeclContext*>(
> -
>  D->getDeclContext()),
> -                                          D->getLocStart(),
> D->getLocation(),
> -                                          name, arrayType, sourceInfo,
> -                                          SC_Static);
> -  backingArray->setTSCSpec(D->getTSCSpec());
> -
> -  // Now clone the InitListExpr to initialize the array instead.
> -  // Incredible hack: we want to use the existing InitListExpr here, so
> we need
> -  // to tell it that it no longer initializes a std::initializer_list.
> -  ArrayRef<Expr*> Inits(const_cast<InitListExpr*>(init)->getInits(),
> -                        init->getNumInits());
> -  Expr *arrayInit = new (ctx) InitListExpr(ctx, init->getLBraceLoc(),
> Inits,
> -                                           init->getRBraceLoc());
> -  arrayInit->setType(arrayType);
> -
> -  if (!cleanups.empty())
> -    arrayInit = ExprWithCleanups::Create(ctx, arrayInit, cleanups);
> -
> -  backingArray->setInit(arrayInit);
> -
> -  // Emit the definition of the array.
> -  EmitGlobalVarDefinition(backingArray);
> -
> -  // Inspect the initializer list to validate it and determine its type.
> -  // FIXME: doing this every time is probably inefficient; caching would
> be nice
> -  RecordDecl *record = init->getType()->castAs<RecordType>()->getDecl();
> -  RecordDecl::field_iterator field = record->field_begin();
> -  if (field == record->field_end()) {
> -    ErrorUnsupported(D, "weird std::initializer_list");
> -    return 0;
> -  }
> -  QualType elementPtr = ctx.getPointerType(elementType.withConst());
> -  // Start pointer.
> -  if (!ctx.hasSameType(field->getType(), elementPtr)) {
> -    ErrorUnsupported(D, "weird std::initializer_list");
> -    return 0;
> -  }
> -  ++field;
> -  if (field == record->field_end()) {
> -    ErrorUnsupported(D, "weird std::initializer_list");
> -    return 0;
> -  }
> -  bool isStartEnd = false;
> -  if (ctx.hasSameType(field->getType(), elementPtr)) {
> -    // End pointer.
> -    isStartEnd = true;
> -  } else if(!ctx.hasSameType(field->getType(), ctx.getSizeType())) {
> -    ErrorUnsupported(D, "weird std::initializer_list");
> -    return 0;
> -  }
> -
> -  // Now build an APValue representing the std::initializer_list.
> -  APValue initListValue(APValue::UninitStruct(), 0, 2);
> -  APValue &startField = initListValue.getStructField(0);
> -  APValue::LValuePathEntry startOffsetPathEntry;
> -  startOffsetPathEntry.ArrayIndex = 0;
> -  startField = APValue(APValue::LValueBase(backingArray),
> -                       CharUnits::fromQuantity(0),
> -                       llvm::makeArrayRef(startOffsetPathEntry),
> -                       /*IsOnePastTheEnd=*/false, 0);
> -
> -  if (isStartEnd) {
> -    APValue &endField = initListValue.getStructField(1);
> -    APValue::LValuePathEntry endOffsetPathEntry;
> -    endOffsetPathEntry.ArrayIndex = numInits;
> -    endField = APValue(APValue::LValueBase(backingArray),
> -                       ctx.getTypeSizeInChars(elementType) * numInits,
> -                       llvm::makeArrayRef(endOffsetPathEntry),
> -                       /*IsOnePastTheEnd=*/true, 0);
> -  } else {
> -    APValue &sizeField = initListValue.getStructField(1);
> -    sizeField = APValue(llvm::APSInt(numElements));
> -  }
> -
> -  // Emit the constant for the initializer_list.
> -  llvm::Constant *llvmInit =
> -      EmitConstantValueForMemory(initListValue, D->getType());
> -  assert(llvmInit && "failed to initialize as constant");
> -  return llvmInit;
> -}
> -
>  unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D,
>                                                   unsigned AddrSpace) {
>    if (LangOpts.CUDA && CodeGenOpts.CUDAIsDevice) {
> @@ -1817,18 +1698,10 @@ void CodeGenModule::EmitGlobalVarDefinit
>      assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
>      Init = EmitNullConstant(D->getType());
>    } else {
> -    // If this is a std::initializer_list, emit the special initializer.
> -    Init = MaybeEmitGlobalStdInitializerListInitializer(D, InitExpr);
> -    // An empty init list will perform zero-initialization, which happens
> -    // to be exactly what we want.
> -    // FIXME: It does so in a global constructor, which is *not* what we
> -    // want.
> +    initializedGlobalDecl = GlobalDecl(D);
> +    Init = EmitConstantInit(*InitDecl);
>
>      if (!Init) {
> -      initializedGlobalDecl = GlobalDecl(D);
> -      Init = EmitConstantInit(*InitDecl);
> -    }
> -    if (!Init) {
>        QualType T = InitExpr->getType();
>        if (D->getType()->isReferenceType())
>          T = D->getType();
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Wed Jun 12 17:31:48 2013
> @@ -1020,8 +1020,6 @@ private:
>
>    void EmitGlobalFunctionDefinition(GlobalDecl GD);
>    void EmitGlobalVarDefinition(const VarDecl *D);
> -  llvm::Constant *MaybeEmitGlobalStdInitializerListInitializer(const
> VarDecl *D,
> -                                                              const Expr
> *init);
>    void EmitAliasDefinition(GlobalDecl GD);
>    void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
>    void EmitObjCIvarInitializations(ObjCImplementationDecl *D);
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jun 12 17:31:48 2013
> @@ -2153,10 +2153,6 @@ Sema::ActOnCXXInClassMemberInitializer(D
>
>    ExprResult Init = InitExpr;
>    if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
> -    if (isa<InitListExpr>(InitExpr) &&
> isStdInitializerList(FD->getType(), 0)) {
> -      Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
> -        << /*at end of ctor*/1 << InitExpr->getSourceRange();
> -    }
>      InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
>      InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
>          ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
> @@ -2550,11 +2546,6 @@ Sema::BuildMemberInitializer(ValueDecl *
>      if (isa<InitListExpr>(Init)) {
>        InitList = true;
>        Args = Init;
> -
> -      if (isStdInitializerList(Member->getType(), 0)) {
> -        Diag(IdLoc, diag::warn_dangling_std_initializer_list)
> -            << /*at end of ctor*/1 << InitRange;
> -      }
>      }
>
>      // Initialize the member.
>
> Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Jun 12 17:31:48 2013
> @@ -1006,6 +1006,7 @@ CanThrowResult Sema::canThrow(const Expr
>    case Expr::CompoundLiteralExprClass:
>    case Expr::CXXConstCastExprClass:
>    case Expr::CXXReinterpretCastExprClass:
> +  case Expr::CXXStdInitializerListExprClass:
>    case Expr::DesignatedInitExprClass:
>    case Expr::ExprWithCleanupsClass:
>    case Expr::ExtVectorElementExprClass:
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jun 12 17:31:48 2013
> @@ -2937,6 +2937,12 @@ static void MaybeProduceObjCObject(Sema
>    }
>  }
>
> +static void TryListInitialization(Sema &S,
> +                                  const InitializedEntity &Entity,
> +                                  const InitializationKind &Kind,
> +                                  InitListExpr *InitList,
> +                                  InitializationSequence &Sequence);
> +
>  /// \brief When initializing from init list via constructor, handle
>  /// initialization of an object of type std::initializer_list<T>.
>  ///
> @@ -2950,25 +2956,23 @@ static bool TryInitializerListConstructi
>    if (!S.isStdInitializerList(DestType, &E))
>      return false;
>
> -  // Check that each individual element can be copy-constructed. But
> since we
> -  // have no place to store further information, we'll recalculate
> everything
> -  // later.
> -  InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
> -      S.Context.getConstantArrayType(E,
> -          llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
> -                      List->getNumInits()),
> -          ArrayType::Normal, 0));
> -  InitializedEntity Element =
> InitializedEntity::InitializeElement(S.Context,
> -      0, HiddenArray);
> -  for (unsigned i = 0, n = List->getNumInits(); i < n; ++i) {
> -    Element.setElementIndex(i);
> -    if (!S.CanPerformCopyInitialization(Element, List->getInit(i))) {
> -      Sequence.SetFailed(
> -          InitializationSequence::FK_InitListElementCopyFailure);
> -      return true;
> -    }
> +  if (S.RequireCompleteType(List->getExprLoc(), E, 0)) {
> +    Sequence.setIncompleteTypeFailure(E);
> +    return true;
>    }
> -  Sequence.AddStdInitializerListConstructionStep(DestType);
> +
> +  // Try initializing a temporary array from the init list.
> +  QualType ArrayType = S.Context.getConstantArrayType(
> +      E.withConst(),
> llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
> +                                 List->getNumInits()),
> +      clang::ArrayType::Normal, 0);
> +  InitializedEntity HiddenArray =
> +      InitializedEntity::InitializeTemporary(ArrayType);
> +  InitializationKind Kind =
> +      InitializationKind::CreateDirectList(List->getExprLoc());
> +  TryListInitialization(S, HiddenArray, Kind, List, Sequence);
> +  if (Sequence)
> +    Sequence.AddStdInitializerListConstructionStep(DestType);
>    return true;
>  }
>
> @@ -3198,12 +3202,6 @@ static void TryValueInitialization(Sema
>                                     InitializationSequence &Sequence,
>                                     InitListExpr *InitList = 0);
>
> -static void TryListInitialization(Sema &S,
> -                                  const InitializedEntity &Entity,
> -                                  const InitializationKind &Kind,
> -                                  InitListExpr *InitList,
> -                                  InitializationSequence &Sequence);
> -
>  /// \brief Attempt list initialization of a reference.
>  static void TryReferenceListInitialization(Sema &S,
>                                             const InitializedEntity
> &Entity,
> @@ -5135,7 +5133,7 @@ PerformConstructorInitialization(Sema &S
>      return ExprError();
>
>    if (shouldBindAsTemporary(Entity))
> -    CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
> +    CurInit = S.MaybeBindToTemporary(CurInit.take());
>
>    return CurInit;
>  }
> @@ -5277,19 +5275,18 @@ static void performLifetimeExtension(Exp
>    if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
>      Init = BTE->getSubExpr();
>
> +  if (CXXStdInitializerListExpr *ILE =
> +          dyn_cast<CXXStdInitializerListExpr>(Init))
> +    return performReferenceExtension(ILE->getSubExpr(), ExtendingD);
> +
>    if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
> -    if (ILE->initializesStdInitializerList() ||
> ILE->getType()->isArrayType()) {
> -      // FIXME: If this is an InitListExpr which creates a
> std::initializer_list
> -      //        object, we also need to lifetime-extend the underlying
> array
> -      //        itself. Fix the representation to explicitly materialize
> an
> -      //        array temporary so we can model this properly.
> +    if (ILE->getType()->isArrayType()) {
>        for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
>          performLifetimeExtension(ILE->getInit(I), ExtendingD);
>        return;
>      }
>
> -    CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl();
> -    if (RD) {
> +    if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
>        assert(RD->isAggregate() && "aggregate init on non-aggregate");
>
>        // If we lifetime-extend a braced initializer which is initializing
> an
> @@ -5319,6 +5316,39 @@ static void performLifetimeExtension(Exp
>    }
>  }
>
> +static void warnOnLifetimeExtension(Sema &S, const InitializedEntity
> &Entity,
> +                                    const Expr *Init, bool
> IsInitializerList,
> +                                    const ValueDecl *ExtendingDecl) {
> +  // Warn if a field lifetime-extends a temporary.
> +  if (isa<FieldDecl>(ExtendingDecl)) {
> +    if (IsInitializerList) {
> +      S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
> +        << /*at end of constructor*/true;
> +      return;
> +    }
> +
> +    bool IsSubobjectMember = false;
> +    for (const InitializedEntity *Ent = Entity.getParent(); Ent;
> +         Ent = Ent->getParent()) {
> +      if (Ent->getKind() != InitializedEntity::EK_Base) {
> +        IsSubobjectMember = true;
> +        break;
> +      }
> +    }
> +    S.Diag(Init->getExprLoc(),
> +           diag::warn_bind_ref_member_to_temporary)
> +      << ExtendingDecl << Init->getSourceRange()
> +      << IsSubobjectMember << IsInitializerList;
> +    if (IsSubobjectMember)
> +      S.Diag(ExtendingDecl->getLocation(),
> +             diag::note_ref_subobject_of_member_declared_here);
> +    else
> +      S.Diag(ExtendingDecl->getLocation(),
> +             diag::note_ref_or_ptr_member_declared_here)
> +        << /*is pointer*/false;
> +  }
> +}
> +
>  ExprResult
>  InitializationSequence::Perform(Sema &S,
>                                  const InitializedEntity &Entity,
> @@ -5570,29 +5600,7 @@ InitializationSequence::Perform(Sema &S,
>            getDeclForTemporaryLifetimeExtension(Entity);
>        if (ExtendingDecl) {
>          performLifetimeExtension(CurInit.get(), ExtendingDecl);
> -
> -        // Warn if a field lifetime-extends a temporary.
> -        if (isa<FieldDecl>(ExtendingDecl)) {
> -          bool IsSubobjectMember = false;
> -          for (const InitializedEntity *Ent = Entity.getParent(); Ent;
> -               Ent = Ent->getParent()) {
> -            if (Ent->getKind() != InitializedEntity::EK_Base) {
> -              IsSubobjectMember = true;
> -              break;
> -            }
> -          }
> -          S.Diag(CurInit.get()->getExprLoc(),
> -                 diag::warn_bind_ref_member_to_temporary)
> -            << ExtendingDecl << CurInit.get()->getSourceRange()
> -            << IsSubobjectMember;
> -          if (IsSubobjectMember)
> -            S.Diag(ExtendingDecl->getLocation(),
> -                   diag::note_ref_subobject_of_member_declared_here);
> -          else
> -            S.Diag(ExtendingDecl->getLocation(),
> -                   diag::note_ref_or_ptr_member_declared_here)
> -              << /*IsPointer*/false;
> -        }
> +        warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
> ExtendingDecl);
>        }
>
>        // Materialize the temporary into memory.
> @@ -5763,16 +5771,10 @@ InitializationSequence::Perform(Sema &S,
>
>      case SK_ListInitialization: {
>        InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
> -      // Hack: We must pass *ResultType if available in order to set the
> type
> -      // of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
> -      // But in 'const X &x = {1, 2, 3};' we're supposed to initialize a
> -      // temporary, not a reference, so we should pass Ty.
> -      // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
> -      // Since this step is never used for a reference directly, we
> explicitly
> -      // unwrap references here and rewrap them afterwards.
> -      // We also need to create a InitializeTemporary entity for this.
> -      QualType Ty = ResultType ? ResultType->getNonReferenceType() :
> Step->Type;
> -      bool IsTemporary = Entity.getType()->isReferenceType();
> +      // If we're not initializing the top-level entity, we need to
> create an
> +      // InitializeTemporary entity for our target type.
> +      QualType Ty = Step->Type;
> +      bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty);
>        InitializedEntity TempEntity =
> InitializedEntity::InitializeTemporary(Ty);
>        InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity;
>        InitListChecker PerformInitList(S, InitEntity,
> @@ -5780,7 +5782,11 @@ InitializationSequence::Perform(Sema &S,
>        if (PerformInitList.HadError())
>          return ExprError();
>
> -      if (ResultType) {
> +      // Hack: We must update *ResultType if available in order to set the
> +      // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
> +      // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
> +      if (ResultType &&
> +          ResultType->getNonReferenceType()->isIncompleteArrayType()) {
>          if ((*ResultType)->isRValueReferenceType())
>            Ty = S.Context.getRValueReferenceType(Ty);
>          else if ((*ResultType)->isLValueReferenceType())
> @@ -5973,56 +5979,35 @@ InitializationSequence::Perform(Sema &S,
>        break;
>
>      case SK_StdInitializerList: {
> -      QualType Dest = Step->Type;
> -      QualType E;
> -      bool Success = S.isStdInitializerList(Dest.getNonReferenceType(),
> &E);
> -      (void)Success;
> -      assert(Success && "Destination type changed?");
> -
> -      // If the element type has a destructor, check it.
> -      if (CXXRecordDecl *RD = E->getAsCXXRecordDecl()) {
> -        if (!RD->hasIrrelevantDestructor()) {
> -          if (CXXDestructorDecl *Destructor = S.LookupDestructor(RD)) {
> -            S.MarkFunctionReferenced(Kind.getLocation(), Destructor);
> -            S.CheckDestructorAccess(Kind.getLocation(), Destructor,
> -                                    S.PDiag(diag::err_access_dtor_temp)
> << E);
> -            if (S.DiagnoseUseOfDecl(Destructor, Kind.getLocation()))
> -              return ExprError();
> -          }
> -        }
> -      }
> +      S.Diag(CurInit.get()->getExprLoc(),
> +             diag::warn_cxx98_compat_initializer_list_init)
> +        << CurInit.get()->getSourceRange();
>
> -      InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
> -      S.Diag(ILE->getExprLoc(),
> diag::warn_cxx98_compat_initializer_list_init)
> -        << ILE->getSourceRange();
> -      unsigned NumInits = ILE->getNumInits();
> -      SmallVector<Expr*, 16> Converted(NumInits);
> -      InitializedEntity HiddenArray =
> InitializedEntity::InitializeTemporary(
> -          S.Context.getConstantArrayType(E,
> -              llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
> -                          NumInits),
> -              ArrayType::Normal, 0));
> -      InitializedEntity Element
> =InitializedEntity::InitializeElement(S.Context,
> -          0, HiddenArray);
> -      for (unsigned i = 0; i < NumInits; ++i) {
> -        Element.setElementIndex(i);
> -        ExprResult Init = S.Owned(ILE->getInit(i));
> -        ExprResult Res = S.PerformCopyInitialization(
> -                             Element, Init.get()->getExprLoc(), Init,
> -                             /*TopLevelOfInitList=*/ true);
> -        if (Res.isInvalid())
> -          return ExprError();
> -        Converted[i] = Res.take();
> +      // Maybe lifetime-extend the array temporary's subobjects to match
> the
> +      // entity's lifetime.
> +      const ValueDecl *ExtendingDecl =
> +          getDeclForTemporaryLifetimeExtension(Entity);
> +      if (ExtendingDecl) {
> +        performLifetimeExtension(CurInit.get(), ExtendingDecl);
> +        warnOnLifetimeExtension(S, Entity, CurInit.get(), true,
> ExtendingDecl);
>        }
> -      InitListExpr *Semantic = new (S.Context)
> -          InitListExpr(S.Context, ILE->getLBraceLoc(),
> -                       Converted, ILE->getRBraceLoc());
> -      Semantic->setSyntacticForm(ILE);
> -      Semantic->setType(Dest);
> -      Semantic->setInitializesStdInitializerList();
> -      CurInit = S.Owned(Semantic);
> +
> +      // Materialize the temporary into memory.
> +      MaterializeTemporaryExpr *MTE = new (S.Context)
> +          MaterializeTemporaryExpr(CurInit.get()->getType(),
> CurInit.get(),
> +                                   /*lvalue reference*/ false,
> ExtendingDecl);
> +
> +      // Wrap it in a construction of a std::initializer_list<T>.
> +      CurInit = S.Owned(
> +          new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE));
> +
> +      // Bind the result, in case the library has given initializer_list a
> +      // non-trivial destructor.
> +      if (shouldBindAsTemporary(Entity))
> +        CurInit = S.MaybeBindToTemporary(CurInit.take());
>        break;
>      }
> +
>      case SK_OCLSamplerInit: {
>        assert(Step->Type->isSamplerT() &&
>               "Sampler initialization on non sampler type.");
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jun 12 17:31:48 2013
> @@ -2639,6 +2639,10 @@ ExprResult TreeTransform<Derived>::Trans
>    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
>      Init = ICE->getSubExprAsWritten();
>
> +  if (CXXStdInitializerListExpr *ILE =
> +          dyn_cast<CXXStdInitializerListExpr>(Init))
> +    return TransformInitializer(ILE->getSubExpr(), CXXDirectInit);
> +
>    // If this is not a direct-initializer, we only need to reconstruct
>    // InitListExprs. Other forms of copy-initialization will be a no-op if
>    // the initializer is already the right type.
> @@ -8548,6 +8552,13 @@ TreeTransform<Derived>::TransformMateria
>  }
>
>  template<typename Derived>
> +ExprResult
> +TreeTransform<Derived>::TransformCXXStdInitializerListExpr(
> +    CXXStdInitializerListExpr *E) {
> +  return getDerived().TransformExpr(E->getSubExpr());
> +}
> +
> +template<typename Derived>
>  ExprResult
>  TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
>    return SemaRef.MaybeBindToTemporary(E);
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Jun 12 17:31:48 2013
> @@ -723,7 +723,6 @@ void ASTStmtReader::VisitInitListExpr(In
>    } else
>      E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx);
>    E->sawArrayRangeDesignator(Record[Idx++]);
> -  E->setInitializesStdInitializerList(Record[Idx++]);
>    unsigned NumInits = Record[Idx++];
>    E->reserveInits(Reader.getContext(), NumInits);
>    if (isArrayFiller) {
> @@ -1227,6 +1226,12 @@ void ASTStmtReader::VisitLambdaExpr(Lamb
>    }
>  }
>
> +void
> +ASTStmtReader::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr
> *E) {
> +  VisitExpr(E);
> +  E->SubExpr = Reader.ReadSubExpr();
> +}
> +
>  void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
>    VisitExplicitCastExpr(E);
>    SourceRange R = ReadSourceRange(Record, Idx);
> @@ -2161,6 +2166,10 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
>        S = new (Context) UserDefinedLiteral(Context, Empty);
>        break;
>
> +    case EXPR_CXX_STD_INITIALIZER_LIST:
> +      S = new (Context) CXXStdInitializerListExpr(Empty);
> +      break;
> +
>      case EXPR_CXX_BOOL_LITERAL:
>        S = new (Context) CXXBoolLiteralExpr(Empty);
>        break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Jun 12 17:31:48 2013
> @@ -735,6 +735,7 @@ static void AddStmtsExprs(llvm::Bitstrea
>    RECORD(EXPR_CXX_CONST_CAST);
>    RECORD(EXPR_CXX_FUNCTIONAL_CAST);
>    RECORD(EXPR_USER_DEFINED_LITERAL);
> +  RECORD(EXPR_CXX_STD_INITIALIZER_LIST);
>    RECORD(EXPR_CXX_BOOL_LITERAL);
>    RECORD(EXPR_CXX_NULL_PTR_LITERAL);
>    RECORD(EXPR_CXX_TYPEID_EXPR);
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Jun 12 17:31:48 2013
> @@ -683,7 +683,6 @@ void ASTStmtWriter::VisitInitListExpr(In
>    else
>      Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
>    Record.push_back(E->hadArrayRangeDesignator());
> -  Record.push_back(E->initializesStdInitializerList());
>    Record.push_back(E->getNumInits());
>    if (isArrayFiller) {
>      // ArrayFiller may have filled "holes" due to designated initializer.
> @@ -1187,6 +1186,12 @@ void ASTStmtWriter::VisitLambdaExpr(Lamb
>    Code = serialization::EXPR_LAMBDA;
>  }
>
> +void
> ASTStmtWriter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E)
> {
> +  VisitExpr(E);
> +  Writer.AddStmt(E->getSubExpr());
> +  Code = serialization::EXPR_CXX_STD_INITIALIZER_LIST;
> +}
> +
>  void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
>    VisitExplicitCastExpr(E);
>    Writer.AddSourceRange(SourceRange(E->getOperatorLoc(),
> E->getRParenLoc()),
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jun 12 17:31:48
> 2013
> @@ -607,6 +607,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
>      case Stmt::CXXDefaultInitExprClass:
>      case Stmt::CXXDependentScopeMemberExprClass:
>      case Stmt::CXXPseudoDestructorExprClass:
> +    case Stmt::CXXStdInitializerListExprClass:
>      case Stmt::CXXTryStmtClass:
>      case Stmt::CXXTypeidExprClass:
>      case Stmt::CXXUuidofExprClass:
>
> Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp (original)
> +++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp Wed Jun
> 12 17:31:48 2013
> @@ -4,7 +4,7 @@ namespace std {
>    typedef decltype(sizeof(int)) size_t;
>
>    template <typename E>
> -  struct initializer_list
> +  struct initializer_list // expected-note 2{{candidate}}
>    {
>      const E *p;
>      size_t n;
> @@ -113,10 +113,14 @@ namespace bullet8 {
>
>  namespace rdar13395022 {
>    struct MoveOnly {
> -    MoveOnly(MoveOnly&&); // expected-note{{copy constructor is
> implicitly deleted because 'MoveOnly' has a user-declared move constructor}}
> +    MoveOnly(MoveOnly&&);
>    };
>
>    void test(MoveOnly mo) {
> -    auto &&list = {mo}; // expected-error{{call to implicitly-deleted
> copy constructor of 'rdar13395022::MoveOnly'}}
> +    // FIXME: These diagnostics are poor.
> +    auto &&list1 = {mo}; // expected-error{{no viable conversion}}
> +    MoveOnly (&&list2)[1] = {mo}; // expected-error{{no viable
> conversion}}
> +    std::initializer_list<MoveOnly> &&list3 = {};
> +    MoveOnly (&&list4)[1] = {}; // expected-error{{uninitialized}}
>    }
>  }
>
> Modified:
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> ---
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
> (original)
> +++
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
> Wed Jun 12 17:31:48 2013
> @@ -1,18 +1,28 @@
> -// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - -verify %s
> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s
> | FileCheck %s --check-prefix=CHECK-STATIC-BL
> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s
> -Dconstexpr= | FileCheck %s --check-prefix=CHECK-DYNAMIC-BL
> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s
> -DUSE_END | FileCheck %s --check-prefix=CHECK-STATIC-BE
> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s
> -DUSE_END -Dconstexpr= | FileCheck %s --check-prefix=CHECK-DYNAMIC-BE
>
>  namespace std {
>    typedef decltype(sizeof(int)) size_t;
>
> -  // libc++'s implementation
>    template <class _E>
>    class initializer_list
>    {
>      const _E* __begin_;
> +#ifdef USE_END
> +    const _E* __end_;
> +#else
>      size_t    __size_;
> +#endif
>
> -    initializer_list(const _E* __b, size_t __s)
> +    constexpr initializer_list(const _E* __b, size_t __s)
>        : __begin_(__b),
> +#ifdef USE_END
> +        __end_(__b + __s)
> +#else
>          __size_(__s)
> +#endif
>      {}
>
>    public:
> @@ -24,14 +34,98 @@ namespace std {
>      typedef const _E* iterator;
>      typedef const _E* const_iterator;
>
> -    initializer_list() : __begin_(nullptr), __size_(0) {}
> +#ifdef USE_END
> +    constexpr initializer_list() : __begin_(nullptr), __end_(nullptr) {}
> +
> +    size_t    size()  const {return __end_ - __begin_;}
> +    const _E* begin() const {return __begin_;}
> +    const _E* end()   const {return __end_;}
> +#else
> +    constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
>
>      size_t    size()  const {return __size_;}
>      const _E* begin() const {return __begin_;}
>      const _E* end()   const {return __begin_ + __size_;}
> +#endif
>    };
>  }
>
> -std::initializer_list<std::initializer_list<int>> pleasefail = {
> -  {1, 2}, {3, 4}, {5, 6} // expected-error {{cannot compile}}
> +std::initializer_list<std::initializer_list<int>> nested = {
> +  {1, 2}, {3, 4}, {5, 6}
>  };
> +
> +// CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32
> 2], align 4
> +// CHECK-STATIC-BL: @_ZGR6nested1 = private constant [2 x i32] [i32 3,
> i32 4], align 4
> +// CHECK-STATIC-BL: @_ZGR6nested2 = private constant [2 x i32] [i32 5,
> i32 6], align 4
> +// CHECK-STATIC-BL: @_ZGR6nested3 = private constant [3 x {{.*}}] [
> +// CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested, i32 0, i32 0), i64 2 },
> +// CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i32 0, i32 0), i64 2 },
> +// CHECK-STATIC-BL:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i32 0, i32 0), i64 2 }
> +// CHECK-STATIC-BL: ], align 8
> +// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr
> inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), i64 3 }, align 8
> +
> +// CHECK-DYNAMIC-BL: @nested = global
> +// CHECK-DYNAMIC-BL: @_ZGR6nested = private global [3 x
> +// CHECK-DYNAMIC-BL: @_ZGR6nested1 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 0)
> +// CHECK-DYNAMIC-BL: store i32 2, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 1)
> +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 0),
> +// CHECK-DYMAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 0, i32 0), align 8
> +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x
> {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
> +// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 0)
> +// CHECK-DYNAMIC-BL: store i32 4, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 1)
> +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 0),
> +// CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 1, i32 0), align 8
> +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x
> {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
> +// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 0)
> +// CHECK-DYNAMIC-BL: store i32 6, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 1)
> +// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 0),
> +// CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 2, i32 0), align 8
> +// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x
> {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
> +// CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 0),
> +// CHECK-DYNAMIC-BL:       {{.*}}** getelementptr inbounds ({{.*}}*
> @nested, i32 0, i32 0), align 8
> +// CHECK-DYNAMIC-BL: store i64 3, i64* getelementptr inbounds ({{.*}}*
> @nested, i32 0, i32 1), align 8
> +
> +// CHECK-STATIC-BE: @_ZGR6nested = private constant [2 x i32] [i32 1, i32
> 2], align 4
> +// CHECK-STATIC-BE: @_ZGR6nested1 = private constant [2 x i32] [i32 3,
> i32 4], align 4
> +// CHECK-STATIC-BE: @_ZGR6nested2 = private constant [2 x i32] [i32 5,
> i32 6], align 4
> +// CHECK-STATIC-BE: @_ZGR6nested3 = private constant [3 x {{.*}}] [
> +// CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested, i32 0, i32 0),
> +// CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8*
> bitcast ([2 x i32]* @_ZGR6nested to i8*), i64 8) to i32*) }
> +// CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i32 0, i32 0),
> +// CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8*
> bitcast ([2 x i32]* @_ZGR6nested1 to i8*), i64 8) to i32*) }
> +// CHECK-STATIC-BE:   {{.*}} { i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i32 0, i32 0),
> +// CHECK-STATIC-BE:            i32* bitcast (i8* getelementptr (i8*
> bitcast ([2 x i32]* @_ZGR6nested2 to i8*), i64 8) to i32*) }
> +// CHECK-STATIC-BE: ], align 8
> +// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr
> inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0),
> +// CHECK-STATIC-BE:                           {{.*}} bitcast ({{.*}}*
> getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested3 to i8*), i64 48) to
> {{.*}}*) }
> +
> +// CHECK-DYNAMIC-BE: @nested = global
> +// CHECK-DYNAMIC-BE: @_ZGR6nested = private global [3 x
> +// CHECK-DYNAMIC-BE: @_ZGR6nested1 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32]
> zeroinitializer
> +// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 0)
> +// CHECK-DYNAMIC-BE: store i32 2, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 1)
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 0, i64 0),
> +// CHECK-DYMAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 0, i32 0), align 8
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested1, i64 1, i64 0),
> +// CHECK-DYMAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 0, i32 1), align 8
> +// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 0)
> +// CHECK-DYNAMIC-BE: store i32 4, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 1)
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 0, i64 0),
> +// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 1, i32 0), align 8
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested2, i64 1, i64 0),
> +// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 1, i32 1), align 8
> +// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 0)
> +// CHECK-DYNAMIC-BE: store i32 6, i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 1)
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 0, i64 0),
> +// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 2, i32 0), align 8
> +// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]*
> @_ZGR6nested3, i64 1, i64 0),
> +// CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 2, i32 1), align 8
> +// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 0, i64 0),
> +// CHECK-DYNAMIC-BE:       {{.*}}** getelementptr inbounds ({{.*}}*
> @nested, i32 0, i32 0), align 8
> +// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]*
> @_ZGR6nested, i64 1, i64 0),
> +// CHECK-DYNAMIC-BE:       {{.*}}** getelementptr inbounds ({{.*}}*
> @nested, i32 0, i32 1), align 8
>
> Modified:
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> ---
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
> (original)
> +++
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
> Wed Jun 12 17:31:48 2013
> @@ -32,8 +32,8 @@ namespace std {
>    };
>  }
>
> -// CHECK: @_ZL25globalInitList1__initlist = internal global [3 x i32]
> [i32 1, i32 2, i32 3]
> -// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr
> inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, {{[^)]*}}), i32*
> +// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32
> 2, i32 3]
> +// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr
> inbounds ([3 x i32]* @_ZGR15globalInitList1, {{[^)]*}}), i32*
>  std::initializer_list<int> globalInitList1 = {1, 2, 3};
>
>  void fn1(int i) {
>
> Modified:
> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
> (original)
> +++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Wed
> Jun 12 17:31:48 2013
> @@ -47,23 +47,43 @@ struct wantslist1 {
>    ~wantslist1();
>  };
>
> -// CHECK: @_ZL25globalInitList1__initlist = internal global [3 x i32]
> [i32 1, i32 2, i32 3]
> -// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr
> inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, i32 0, i32 0),
> i{{32|64}} 3 }
> +// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32
> 2, i32 3]
> +// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr
> inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 }
>  std::initializer_list<int> globalInitList1 = {1, 2, 3};
>
>  namespace thread_local_global_array {
> -  // CHECK: @_ZN25thread_local_global_arrayL11x__initlistE = internal
> thread_local global [4 x i32] [i32 1, i32 2, i32 3, i32 4]
> -  // CHECK: @_ZN25thread_local_global_array1xE = thread_local global
> {{.*}} @_ZN25thread_local_global_arrayL11x__initlistE, {{.*}} i64 4
> +  // FIXME: We should be able to constant-evaluate this even though the
> +  // initializer is not a constant expression (pointers to thread_local
> +  // objects aren't really a problem).
> +  //
> +  // CHECK: @_ZN25thread_local_global_array1xE = thread_local global
> +  // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local
> global [4 x i32]
>    std::initializer_list<int> thread_local x = { 1, 2, 3, 4 };
>  }
>
> -// CHECK: @_ZL25globalInitList2__initlist = internal global [2 x %{{[^
> ]*}}] zeroinitializer
> -// CHECK: @globalInitList2 = global %{{[^ ]+}} { %[[WITHARG:[^ *]+]]*
> getelementptr inbounds ([2 x
> +// CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
> +// CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^
> ]*]]] zeroinitializer
>  // CHECK: appending global
> +
> +
> +// thread_local initializer:
> +// CHECK: define internal void
> +// CHECK: store i32 1, i32* getelementptr inbounds ([4 x i32]*
> @_ZGRN25thread_local_global_array1xE, i64 0, i64 0)
> +// CHECK: store i32 2, i32* getelementptr inbounds ([4 x i32]*
> @_ZGRN25thread_local_global_array1xE, i64 0, i64 1)
> +// CHECK: store i32 3, i32* getelementptr inbounds ([4 x i32]*
> @_ZGRN25thread_local_global_array1xE, i64 0, i64 2)
> +// CHECK: store i32 4, i32* getelementptr inbounds ([4 x i32]*
> @_ZGRN25thread_local_global_array1xE, i64 0, i64 3)
> +// CHECK: store i32* getelementptr inbounds ([4 x i32]*
> @_ZGRN25thread_local_global_array1xE, i64 0, i64 0),
> +// CHECK:       i32** getelementptr inbounds ({{.*}}*
> @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8
> +// CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}*
> @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8
> +
> +
>  // CHECK: define internal void
> -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]*
> getelementptr inbounds ([2 x %[[WITHARG]]]*
> @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 0
> -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]*
> getelementptr inbounds ([2 x %[[WITHARG]]]*
> @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 1
> +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]*
> getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2,
> i{{32|64}} 0, i{{32|64}} 0
> +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]*
> getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2,
> i{{32|64}} 0, i{{32|64}} 1
>  // CHECK: __cxa_atexit
> +// CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]*
> @_ZGR15globalInitList2, i64 0, i64 0),
> +// CHECK:       %[[WITHARG]]** getelementptr inbounds (%{{.*}}*
> @globalInitList2, i32 0, i32 0), align 8
> +// CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}*
> @globalInitList2, i32 0, i32 1), align 8
>  // CHECK: call void @_ZN10destroyme1D1Ev
>  // CHECK: call void @_ZN10destroyme1D1Ev
>  std::initializer_list<witharg1> globalInitList2 = {
> @@ -281,10 +301,56 @@ namespace dtors {
>      S();
>      ~S();
>    };
> +  void z();
> +
> +  // CHECK: define void @_ZN5dtors1fEv(
>    void f() {
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.begin)
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.element)
>      std::initializer_list<S>{ S(), S() };
> +
> +    // Destruction loop for underlying array.
> +    // CHECK: br label
> +    // CHECK: call void @_ZN5dtors1SD1Ev(
> +    // CHECK: br i1
> +
> +    // CHECK: call void @_ZN5dtors1zEv(
> +    z();
> +
> +    // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
>    }
> +
> +  // CHECK: define void @_ZN5dtors1gEv(
>    void g() {
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.begin)
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.element)
>      auto x = std::initializer_list<S>{ S(), S() };
> +
> +    // Destruction loop for underlying array.
> +    // CHECK: br label
> +    // CHECK: call void @_ZN5dtors1SD1Ev(
> +    // CHECK: br i1
> +
> +    // CHECK: call void @_ZN5dtors1zEv(
> +    z();
> +
> +    // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
> +  }
> +
> +  // CHECK: define void @_ZN5dtors1hEv(
> +  void h() {
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.begin)
> +    // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"*
> %arrayinit.element)
> +    std::initializer_list<S> x = { S(), S() };
> +
> +    // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
> +
> +    // CHECK: call void @_ZN5dtors1zEv(
> +    z();
> +
> +    // Destruction loop for underlying array.
> +    // CHECK: br label
> +    // CHECK: call void @_ZN5dtors1SD1Ev(
> +    // CHECK: br i1
>    }
>  }
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Wed Jun 12
> 17:31:48 2013
> @@ -1596,3 +1596,44 @@ namespace AfterError {
>    }
>    constexpr int k = error(); // expected-error {{must be initialized by a
> constant expression}}
>  }
> +
> +namespace std {
> +  typedef decltype(sizeof(int)) size_t;
> +
> +  template <class _E>
> +  class initializer_list
> +  {
> +    const _E* __begin_;
> +    size_t    __size_;
> +
> +    constexpr initializer_list(const _E* __b, size_t __s)
> +      : __begin_(__b),
> +        __size_(__s)
> +    {}
> +
> +  public:
> +    typedef _E        value_type;
> +    typedef const _E& reference;
> +    typedef const _E& const_reference;
> +    typedef size_t    size_type;
> +
> +    typedef const _E* iterator;
> +    typedef const _E* const_iterator;
> +
> +    constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
> +
> +    constexpr size_t    size()  const {return __size_;}
> +    constexpr const _E* begin() const {return __begin_;}
> +    constexpr const _E* end()   const {return __begin_ + __size_;}
> +  };
> +}
> +
> +namespace InitializerList {
> +  constexpr int sum(const int *b, const int *e) {
> +    return b != e ? *b + sum(b+1, e) : 0;
> +  }
> +  constexpr int sum(std::initializer_list<int> ints) {
> +    return sum(ints.begin(), ints.end());
> +  }
> +  static_assert(sum({1, 2, 3, 4, 5}) == 15, "");
> +}
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp Wed Jun 12
> 17:31:48 2013
> @@ -725,3 +725,43 @@ namespace modify_temporary_during_constr
>    static_assert(a.y == 54, "");
>    constexpr int k = a.temporary++; // expected-error {{constant
> expression}} expected-note {{outside the expression that created the
> temporary}}
>  }
> +
> +namespace std {
> +  typedef decltype(sizeof(int)) size_t;
> +
> +  template <class _E>
> +  class initializer_list
> +  {
> +    const _E* __begin_;
> +    size_t    __size_;
> +
> +    constexpr initializer_list(const _E* __b, size_t __s)
> +      : __begin_(__b),
> +        __size_(__s)
> +    {}
> +
> +  public:
> +    typedef _E        value_type;
> +    typedef const _E& reference;
> +    typedef const _E& const_reference;
> +    typedef size_t    size_type;
> +
> +    typedef const _E* iterator;
> +    typedef const _E* const_iterator;
> +
> +    constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
> +
> +    constexpr size_t    size()  const {return __size_;}
> +    constexpr const _E* begin() const {return __begin_;}
> +    constexpr const _E* end()   const {return __begin_ + __size_;}
> +  };
> +}
> +
> +namespace InitializerList {
> +  constexpr int sum(std::initializer_list<int> ints) {
> +    int total = 0;
> +    for (int n : ints) total += n;
> +    return total;
> +  }
> +  static_assert(sum({1, 2, 3, 4, 5}) == 15, "");
> +}
>
> Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
> (original)
> +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Wed
> Jun 12 17:31:48 2013
> @@ -144,7 +144,7 @@ namespace PR12119 {
>    template<typename T> void
> g(std::initializer_list<std::initializer_list<T>>);
>
>    void foo() {
> -    f({0, {1}});
> +    f({0, {1}}); // expected-warning{{braces around scalar initializer}}
>      g({{0, 1}, {2, 3}});
>      std::initializer_list<int> il = {1, 2};
>      g({il, {2, 3}});
>
> Modified: cfe/trunk/tools/libclang/CXCursor.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/CXCursor.cpp (original)
> +++ cfe/trunk/tools/libclang/CXCursor.cpp Wed Jun 12 17:31:48 2013
> @@ -216,6 +216,7 @@ CXCursor cxcursor::MakeCXCursor(const St
>    case Stmt::CXXBindTemporaryExprClass:
>    case Stmt::CXXDefaultArgExprClass:
>    case Stmt::CXXDefaultInitExprClass:
> +  case Stmt::CXXStdInitializerListExprClass:
>    case Stmt::CXXScalarValueInitExprClass:
>    case Stmt::CXXUuidofExprClass:
>    case Stmt::ChooseExprClass:
>
> Modified: cfe/trunk/tools/libclang/RecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/RecursiveASTVisitor.h?rev=183872&r1=183871&r2=183872&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/tools/libclang/RecursiveASTVisitor.h Wed Jun 12 17:31:48 2013
> @@ -2095,6 +2095,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {
>  DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
>  DEF_TRAVERSE_STMT(ExprWithCleanups, { })
>  DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
> +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { })
>  DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
>    TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
>    if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130613/2ad4def2/attachment.html>


More information about the cfe-commits mailing list