From: Sebastian Redl Date: Sat, 24 Sep 2011 17:48:14 +0000 (+0000) Subject: Treat list-initialization of scalars as a first-class citizen in C++11. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cea8d966f826554f0679595e9371e314e8dbc1cf;p=clang Treat list-initialization of scalars as a first-class citizen in C++11. Allow empty initializer lists for scalars, which mean value-initialization. Constant evaluation for single-element and empty initializer lists for scalars. Codegen for empty initializer lists for scalars. Test case comes in next commit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140459 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 2de72f392e..524afb11b6 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -484,6 +484,13 @@ public: return Visit(E->getSubExpr()); } } + + bool VisitInitListExpr(const InitListExpr *E) { + if (Info.Ctx.getLangOptions().CPlusPlus0x && E->getNumInits() == 1) + return Visit(E->getInit(0)); + return Error(E); + } + // FIXME: Missing: __real__, __imag__ }; @@ -1079,7 +1086,9 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); - + + bool VisitInitListExpr(const InitListExpr *E); + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1932,6 +1941,17 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { return Success(E->getValue(), E); } +bool IntExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (!Info.Ctx.getLangOptions().CPlusPlus0x) + return Error(E); + + if (E->getNumInits() == 0) + return Success(0, E); + + assert(E->getNumInits() == 1 && "Excess initializers for integer in C++11."); + return Visit(E->getInit(0)); +} + //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// @@ -1965,6 +1985,8 @@ public: bool VisitDeclRefExpr(const DeclRefExpr *E); + bool VisitInitListExpr(const InitListExpr *E); + // FIXME: Missing: array subscript of vector, member of vector, // ImplicitValueInitExpr }; @@ -2233,6 +2255,19 @@ bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExp return true; } +bool FloatExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (!Info.Ctx.getLangOptions().CPlusPlus0x) + return Error(E); + + if (E->getNumInits() == 0) { + Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); + return true; + } + + assert(E->getNumInits() == 1 && "Excess initializers for integer in C++11."); + return Visit(E->getInit(0)); +} + //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// @@ -2264,7 +2299,7 @@ public: bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); - // FIXME Missing: ImplicitValueInitExpr + // FIXME Missing: ImplicitValueInitExpr, InitListExpr }; } // end anonymous namespace @@ -2766,7 +2801,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: - case Expr::InitListExprClass: case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: @@ -2813,6 +2847,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::MaterializeTemporaryExprClass: return ICEDiag(2, E->getLocStart()); + case Expr::InitListExprClass: + if (Ctx.getLangOptions().CPlusPlus0x) { + const InitListExpr *ILE = cast(E); + if (ILE->getNumInits() == 0) + return NoDiag(); + if (ILE->getNumInits() == 1) + return CheckICE(ILE->getInit(0), Ctx); + // Fall through for more than 1 expression. + } + return ICEDiag(2, E->getLocStart()); + case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 264a71403a..c2f871334f 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -837,9 +837,14 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { llvm::VectorType *VType = dyn_cast(ConvertType(E->getType())); - // We have a scalar in braces. Just use the first element. - if (!VType) + if (!VType) { + if (NumInitElements == 0) { + // C++11 value-initialization for the scalar. + return EmitNullValue(E->getType()); + } + // We have a scalar in braces. Just use the first element. return Visit(E->getInit(0)); + } unsigned ResElts = VType->getNumElements(); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7c27e6fbae..2e4b2362b1 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -877,11 +877,12 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { - // FIXME: Allowed in C++11. - if (!VerifyOnly) - SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) - << IList->getSourceRange(); - hadError = true; + if (!SemaRef.getLangOptions().CPlusPlus0x) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) + << IList->getSourceRange(); + hadError = true; + } ++Index; ++StructuredIndex; return; diff --git a/test/CodeGenCXX/cxx0x-initializer-scalars.cpp b/test/CodeGenCXX/cxx0x-initializer-scalars.cpp new file mode 100644 index 0000000000..a951dd1344 --- /dev/null +++ b/test/CodeGenCXX/cxx0x-initializer-scalars.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++0x -S -emit-llvm -o - %s | FileCheck %s + +void f() +{ + // CHECK: store i32 0 + int i{}; +}