diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-12 18:54:33 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-12 18:54:33 +0000 |
commit | ec789163a42a7be654ac34aadb750b508954d53c (patch) | |
tree | 6546d1b5f6eb005f81af63726a6ea314f132001b /lib/AST/ExprConstant.cpp | |
parent | 37969b7e14d6a4dfd934ef6d3738cc90b832ec1d (diff) |
constexpr: initialization of a union from an empty initializer-list should
zero-initialize the first union member. Also fix a bug where initializing an
array of types compatible with wchar_t from a wide string literal failed in C,
and fortify the C++ tests in this area. This part can't be tested without a code
change to enable array evaluation in C (where an existing test fails).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148035 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 9df53cd5bf..0cae13850d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -3015,14 +3015,20 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); if (RD->isUnion()) { - Result = APValue(E->getInitializedFieldInUnion()); - if (!E->getNumInits()) + const FieldDecl *Field = E->getInitializedFieldInUnion(); + Result = APValue(Field); + if (!Field) return true; + + // If the initializer list for a union does not contain any elements, the + // first element of the union is value-initialized. + ImplicitValueInitExpr VIE(Field->getType()); + const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE; + LValue Subobject = This; - HandleLValueMember(Info, E->getInit(0), Subobject, - E->getInitializedFieldInUnion(), &Layout); + HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout); return EvaluateConstantExpression(Result.getUnionValue(), Info, - Subobject, E->getInit(0)); + Subobject, InitExpr); } assert((!isa<CXXRecordDecl>(RD) || !cast<CXXRecordDecl>(RD)->getNumBases()) && @@ -3065,6 +3071,10 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { const CXXConstructorDecl *FD = E->getConstructor(); bool ZeroInit = E->requiresZeroInitialization(); if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { + // If we've already performed zero-initialization, we're already done. + if (!Result.isUninit()) + return true; + if (ZeroInit) return ZeroInitialization(E); @@ -3391,7 +3401,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] // an appropriately-typed string literal enclosed in braces. - if (E->getNumInits() == 1 && CAT->getElementType()->isAnyCharacterType() && + if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() && Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) { LValue LV; if (!EvaluateLValue(E->getInit(0), LV, Info)) @@ -3446,7 +3456,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (!CAT) return Error(E); - Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue()); + bool HadZeroInit = !Result.isUninit(); + if (!HadZeroInit) + Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue()); if (!Result.hasArrayFiller()) return true; @@ -3454,6 +3466,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { bool ZeroInit = E->requiresZeroInitialization(); if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { + if (HadZeroInit) + return true; + if (ZeroInit) { LValue Subobject = This; Subobject.addArray(Info, E, CAT); @@ -3485,7 +3500,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { LValue Subobject = This; Subobject.addArray(Info, E, CAT); - if (ZeroInit) { + if (ZeroInit && !HadZeroInit) { ImplicitValueInitExpr VIE(CAT->getElementType()); if (!EvaluateConstantExpression(Result.getArrayFiller(), Info, Subobject, &VIE)) |